diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 490a608..0000000 --- a/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules/ -coverage/ -logs/ -dist/ diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 2498e96..0000000 --- a/.eslintrc +++ /dev/null @@ -1,27 +0,0 @@ -{ - "extends": "airbnb", - "parserOptions": { - "sourceType": "script", - }, - "rules": { - "strict": 0, - no-param-reassign: [ - "error", - { "props": false } - ], - "no-console": 0 - }, - "globals": { - "describe": true, - "it": true, - "after": true, - "afterEach": true, - "before": true, - "beforeEach": true, - "should": true - }, - "env": { - "node": true, - "mocha": true - } -} diff --git a/.travis.yml b/.travis.yml index bb97b4d..1a4fb20 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ script: - docker run --name vault -e 'SKIP_SETCAP=true' -d -p "8200:8200" vault - docker ps - docker logs vault - - npm run coverage + - npm run complete-test after_success: - codecov diff --git a/Dockerfile b/Dockerfile index e984540..5062fe1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM node:8.6-alpine +FROM node:8.9.4 WORKDIR /app COPY package.json /app -RUN npm install +RUN yarn COPY . /app diff --git a/README.md b/README.md index a0b0f40..5157927 100644 --- a/README.md +++ b/README.md @@ -5,74 +5,78 @@ [![Download Status](https://img.shields.io/npm/dm/node-vault.svg?style=flat-square)](https://www.npmjs.com/package/node-vault) [![Dependency Status](https://img.shields.io/david/kr1sp1n/node-vault.svg?style=flat-square)](https://david-dm.org/kr1sp1n/node-vault) -A client for the HTTP API of HashiCorp's [Vault] written for Node.js. +NodeJS API client for HashiCorp's [Vault] -## install -make sure to use node.js version >= 6 +## Install +`node-vault` supports Node.js v6 and above. + # yarn + yarn add node-vault + + # npm npm install node-vault -## test +## Usage -Run tests inside docker to do also nice integration testing: +**[All features]** - docker-compose up --force-recreate test - -This will create containers for vault, postgres and running the tests inside -docker. - - -## usage - -### init and unseal +### Init and unseal ```javascript -var options = { +const options = { apiVersion: 'v1', // default endpoint: 'http://127.0.0.1:8200', // default - token: '1234' // optional client token; can be fetched after valid initialization of the server -}; + // VAULT_ADDR environment variable is also available + token: '' // client authentication token, optional + // VAULT_TOKEN environment variable is also available +} // get new instance of the client -var vault = require("node-vault")(options); +const vault = require('node-vault')(options) -// init vault server -vault.init({ secret_shares: 1, secret_threshold: 1 }) -.then( (result) => { - var keys = result.keys; +const run = async () => { + // init vault server + const initData = await vault.init({ secret_shares: 1, secret_threshold: 1 }) // set token for all following requests - vault.token = result.root_token; + vault.login(initData.root_token) // unseal vault server - return vault.unseal({ secret_shares: 1, key: keys[0] }) -}) -.catch(console.error); + const [key] = initData.keys + await vault.unseal({ secret_shares: 1, key }) +} + +run().catch(console.error) ``` -### write, read and delete secrets +### Write, read and delete secrets ```javascript -vault.write('secret/hello', { value: 'world', lease: '1s' }) -.then( () => vault.read('secret/hello')) -.then( () => vault.delete('secret/hello')) -.catch(console.error); +const run = async () => { + await vault.write('secret/hello', { value: 'world', lease: '1s' }) + await vault.read('secret/hello') + await vault.delete('secret/hello') +} + +run().catch(console.error) ``` -## docs -Just generate [docco] docs via `npm run docs`. +## Code documentation +Generate [docco] docs via `yarn docs`. -## examples -Please have a look at the [examples] and the generated [feature list] to see what is already implemented. +## Examples and feature list +Have a look at the [examples] and the generated [feature list] to see what is implemented. -Instead of installing all the dependencies like vault itself, postgres and other stuff you can +When running the examples, instead of installing all the dependencies like vault, postgres and other stuff you can use [docker] and [docker-compose] to link and run multiple docker containers with all of its dependencies. +> Note that node v8+ is required to run the examples, due to the usage of `async/await`. + ```bash git clone git@github.com:kr1sp1n/node-vault.git cd node-vault -docker-compose up vault +docker-compose up --force-recreate vault # or use "yarn refresh-docker-vault" ``` Now you can run the examples from another terminal window. @@ -92,13 +96,29 @@ Now you are able to run all of the other [examples]: node example/policies.js ``` +You can also init vault and run all of the examples in one go by running `yarn examples` (which just executes [examples/all.js]) + +## Testing + +You can run the automated tests with `yarn test`. +To run tests inside docker (making it very easy to run the integration tests) simply run: + + docker-compose up --force-recreate test + +There's also this yarn alias available: `yarn docker-test`. + +> Note that you will need to install and setup [docker] and [docker-compose] + +This will create containers for vault, postgres and the tests themselves. + -[examples]: https://github.com/kr1sp1n/node-vault/tree/master/example -[docker-compose.yml]: https://github.com/kr1sp1n/node-vault/tree/master/docker-compose.yml +[examples]: /examples +[examples/all.js]: examples/all.js +[docker-compose.yml]: /docker-compose.yml [Vault]: https://vaultproject.io/ -[docker-compose]: https://www.docker.com/docker-compose -[docker]: http://docs.docker.com/ -[docker toolbox]: https://www.docker.com/toolbox -[docco]: http://jashkenas.github.io/docco -[feature list]: https://github.com/kr1sp1n/node-vault/tree/master/features.md +[docker]: https://docs.docker.com/ +[docker-compose]: https://docs.docker.com/compose/ +[docco]: http://ashkenas.com/docco/ +[All features]: features.md +[feature list]: features.md diff --git a/docker-compose.yml b/docker-compose.yml index 6ed9604..e882082 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '2' services: test: build: . - command: npm run coverage + command: yarn complete-test environment: - VAULT_ADDR=http://vault:8200 volumes: @@ -13,11 +13,11 @@ services: vault: image: vault volumes: - - $PWD/example:/tmp/example + - $PWD/examples:/tmp/examples - $PWD/logs/:/tmp/logs cap_add: - IPC_LOCK - command: server -config /tmp/example/config.hcl + command: server -config /tmp/examples/config.hcl ports: - "8200:8200" depends_on: diff --git a/example/audits.js b/example/audits.js deleted file mode 100644 index 809fd68..0000000 --- a/example/audits.js +++ /dev/null @@ -1,16 +0,0 @@ -// file: example/audits.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode -const vault = require('./../src/index')(); -const path = '/tmp/logs/test.log'; - -vault.audits() -.then((result) => { - if (result.hasOwnProperty('testlog/')) return undefined; - return vault.enableAudit({ name: 'testlog', type: 'file', options: { path } }); -}) -.then(() => vault.write('secret/hello', { value: 'world', lease: '1s' })) -.then(() => vault.read('secret/hello')) -.then(() => vault.delete('secret/hello')) -.then(() => vault.disableAudit({ name: 'testlog' })) -.catch((err) => console.error(err.message)); diff --git a/example/auth.js b/example/auth.js deleted file mode 100644 index 21f6301..0000000 --- a/example/auth.js +++ /dev/null @@ -1,15 +0,0 @@ -// file: example/auth.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -const options = { - requestOptions: { - followAllRedirects: true, - }, -}; - -vault.auths(options) -.then(console.log) -.catch((err) => console.error(err.message)); diff --git a/example/auth_approle.js b/example/auth_approle.js deleted file mode 100644 index fb78c21..0000000 --- a/example/auth_approle.js +++ /dev/null @@ -1,30 +0,0 @@ -// file: example/auth_approle.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); -const mountPoint = 'approle'; -const roleName = 'test-role'; - -vault.auths() -.then((result) => { - if (result.hasOwnProperty('approle/')) return undefined; - return vault.enableAuth({ - mount_point: mountPoint, - type: 'approle', - description: 'Approle auth', - }); -}) -.then(() => vault.addApproleRole({ role_name: roleName, policies: 'dev-policy, test-policy' })) -.then(() => Promise.all([vault.getApproleRoleId({ role_name: roleName }), - vault.getApproleRoleSecret({ role_name: roleName })]) -) -.then((result) => { - const roleId = result[0].data.role_id; - const secretId = result[1].data.secret_id; - return vault.approleLogin({ role_id: roleId, secret_id: secretId }); -}) -.then((result) => { - console.log(result); -}) -.catch((err) => console.error(err.message)); diff --git a/example/auth_github.js b/example/auth_github.js deleted file mode 100644 index ad3946b..0000000 --- a/example/auth_github.js +++ /dev/null @@ -1,24 +0,0 @@ -// file: example/auth_github.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode -const vault = require('./../src/index')(); - -const org = process.env.GITHUB_ORG; -const team = process.env.GITHUB_TEAM || 'owners'; -const token = process.env.GITHUB_TOKEN; -const mountPoint = 'github'; - -vault.auths() -.then((result) => { - if (result.hasOwnProperty('github/')) return undefined; - return vault.enableAuth({ - mount_point: mountPoint, - type: 'github', - description: 'GitHub auth', - }); -}) -.then(() => vault.write('auth/github/config', { organization: org })) -.then(() => vault.write(`auth/github/map/teams/${team}`, { value: 'root' })) -.then(() => vault.githubLogin({ token })) -.then(console.log) -.catch((err) => console.error(err.message)); diff --git a/example/auth_ldap.js b/example/auth_ldap.js deleted file mode 100644 index a046256..0000000 --- a/example/auth_ldap.js +++ /dev/null @@ -1,22 +0,0 @@ -// file: example/auth_ldap.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode -const vault = require('./../src/index')(); - -const mountPoint = 'auth'; -const username = 'me'; -const password = 'foo'; - -vault.auths() -.then((result) => { - if (result.hasOwnProperty('ldap/')) return undefined; - return vault.enableAuth({ - mount_point: mountPoint, - type: 'ldap', - description: 'ldap auth', - }); -}) -.then(() => vault.write(`auth/ldap/users/${username}`, { password, policies: 'root' })) -.then(() => vault.ldapLogin({ username, password })) -.then(console.log) -.catch((err) => console.error(err.message)); diff --git a/example/auth_userpass.js b/example/auth_userpass.js deleted file mode 100644 index f0e9c45..0000000 --- a/example/auth_userpass.js +++ /dev/null @@ -1,22 +0,0 @@ -// file: example/auth_userpass.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode -const vault = require('./../src/index')(); - -const mountPoint = 'userpass'; -const username = 'me'; -const password = 'foo'; - -vault.auths() -.then((result) => { - if (result.hasOwnProperty('userpass/')) return undefined; - return vault.enableAuth({ - mount_point: mountPoint, - type: 'userpass', - description: 'userpass auth', - }); -}) -.then(() => vault.write(`auth/userpass/users/${username}`, { password, policies: 'root' })) -.then(() => vault.userpassLogin({ username, password })) -.then(console.log) -.catch((err) => console.error(err.message)); diff --git a/example/health.js b/example/health.js deleted file mode 100644 index 5172688..0000000 --- a/example/health.js +++ /dev/null @@ -1,9 +0,0 @@ -// file: example/health.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index.js')(); - -vault.health() -.then(console.log) -.catch((err) => console.error(err.message)); diff --git a/example/help.js b/example/help.js deleted file mode 100644 index 3931fc0..0000000 --- a/example/help.js +++ /dev/null @@ -1,9 +0,0 @@ -// file: example/help.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index.js')(); - -vault.help('sys/policy') -.then(console.log) -.catch((err) => console.error(err.message)); diff --git a/example/init.js b/example/init.js deleted file mode 100644 index 71be75b..0000000 --- a/example/init.js +++ /dev/null @@ -1,19 +0,0 @@ -// file: example/init.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -vault.initialized() -.then((result) => { - console.log(result); - return vault.init({ secret_shares: 1, secret_threshold: 1 }); -}) -.then((result) => { - console.log(result); - vault.token = result.root_token; - const key = result.keys[0]; - return vault.unseal({ secret_shares: 1, key }); -}) -.then(console.log) -.catch((err) => console.error(err.message)); diff --git a/example/leases.js b/example/leases.js deleted file mode 100644 index cd74694..0000000 --- a/example/leases.js +++ /dev/null @@ -1,13 +0,0 @@ -// file: example/leases.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode -const vault = require('./../src/index')(); - -// TODO fix example for leases because generic backend does not generate a lease_id anymore -// See: https://github.com/hashicorp/vault/issues/877 - -vault.write('secret/hello', { value: 'world', lease: '10h' }) -.then(() => vault.read('secret/hello')) -.then((result) => vault.revoke({ lease_id: result.lease_id })) -.then(() => vault.revokePrefix({ path_prefix: 'secret' })) -.catch((err) => console.error(err.message)); diff --git a/example/mount_postgresql.js b/example/mount_postgresql.js deleted file mode 100644 index 633b69c..0000000 --- a/example/mount_postgresql.js +++ /dev/null @@ -1,32 +0,0 @@ -// file: example/mount_postgresql.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -const connection = 'postgresql://root:test@postgres:5432/postgres?sslmode=disable'; - -const query = "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID " + -"UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"; - -const configure = () => vault.write('postgresql/config/lease', { lease: '1h', lease_max: '24h' }) - .then(() => vault.write('postgresql/config/connection', { value: connection })); - -const createRole = () => vault.write('postgresql/roles/readonly', { sql: query }); -const getCredentials = () => vault.read('postgresql/creds/readonly'); - -const run = () => configure() - .then(createRole) - .then(getCredentials) - .then(console.log); - -vault.mounts() -.then((result) => { - if (result.hasOwnProperty('postgresql/')) return run(); - return vault.mount({ - mount_point: 'postgresql', - type: 'postgresql', - description: 'postgresql mount test', - }).then(run); -}) -.catch((err) => console.error(err.message)); diff --git a/example/pass_request_options.js b/example/pass_request_options.js deleted file mode 100644 index 19bb58d..0000000 --- a/example/pass_request_options.js +++ /dev/null @@ -1,21 +0,0 @@ -// file: example/pass_request_options.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -const options = { - headers: { - 'X-HELLO': 'world', - }, - agentOptions: { - cert: 'mycert', - key: 'mykey', - passphrase: 'password', - securityOptions: 'SSL_OP_NO_SSLv3', - }, -}; - -vault.help('sys/policy', options) -.then(() => vault.help('sys/mounts')) -.catch((err) => console.error(err.message)); diff --git a/example/policies.js b/example/policies.js deleted file mode 100644 index 9a6cc89..0000000 --- a/example/policies.js +++ /dev/null @@ -1,21 +0,0 @@ -// file: example/policies.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -vault.policies() -.then((result) => { - console.log(result); - return vault.addPolicy({ - name: 'mypolicy', - rules: '{ "path": { "secret/*": { "policy": "write" } } }', - }); -}) -.then(() => vault.getPolicy({ name: 'mypolicy' })) -.then(vault.policies) -.then((result) => { - console.log(result); - return vault.removePolicy({ name: 'mypolicy' }); -}) -.catch((err) => console.error(err.message)); diff --git a/example/rotate.js b/example/rotate.js deleted file mode 100644 index 9ce8dbd..0000000 --- a/example/rotate.js +++ /dev/null @@ -1,7 +0,0 @@ -// file: example/rotate.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -vault.rotate().catch((err) => console.error(err.message)); diff --git a/example/secret_mounts.js b/example/secret_mounts.js deleted file mode 100644 index 4624cb9..0000000 --- a/example/secret_mounts.js +++ /dev/null @@ -1,14 +0,0 @@ -// file: example/secret_mounts.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -vault.mounts() -.then(() => vault.mount({ mount_point: 'test', type: 'generic', description: 'just a test' })) -.then(() => vault.write('test/hello', { value: 'world', lease: '1s' })) -.then(() => vault.remount({ from: 'test', to: 'test2' })) -.then(() => vault.read('test2/hello')) -.then(console.log) -.then(() => vault.unmount({ mount_point: 'test2' })) -.catch((err) => console.error(err.message)); diff --git a/example/status.js b/example/status.js deleted file mode 100644 index e3eb8fb..0000000 --- a/example/status.js +++ /dev/null @@ -1,9 +0,0 @@ -// file: example/status.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -vault.status() -.then(console.log) -.catch((err) => console.error(err.message)); diff --git a/example/token.js b/example/token.js deleted file mode 100644 index a8ebc3f..0000000 --- a/example/token.js +++ /dev/null @@ -1,17 +0,0 @@ -// file: example/token.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -vault.tokenCreate() -.then((result) => { - console.log(result); - const newToken = result.auth; - return vault.tokenLookup({ token: newToken.client_token }) - .then(() => vault.tokenLookupAccessor({ accessor: newToken.accessor })); -}) -.then((result) => { - console.log(result); -}) -.catch((err) => console.error(err.message)); diff --git a/example/write_read_delete.js b/example/write_read_delete.js deleted file mode 100644 index 9ddc4aa..0000000 --- a/example/write_read_delete.js +++ /dev/null @@ -1,10 +0,0 @@ -// file: example/write_read_delete.js - -process.env.DEBUG = 'node-vault'; // switch on debug mode - -const vault = require('./../src/index')(); - -vault.write('secret/hello', { value: 'world', lease: '1s' }) -.then(() => vault.read('secret/hello')) -.then(() => vault.delete('secret/hello')) -.catch((err) => console.error(err.message)); diff --git a/examples/all.js b/examples/all.js new file mode 100644 index 0000000..6a39f25 --- /dev/null +++ b/examples/all.js @@ -0,0 +1,38 @@ +const fs = require('fs-extra') +const init = require('./init') +const vault = require('../src/main')() + +const runExamples = async (examples, vault) => { + if (!examples.length) return + const nextExample = examples.shift() + console.log('\n\n\n') + await nextExample(vault).catch(console.error) + await runExamples(examples, vault) +} + +const run = async () => { + const files = await fs.readdir(__dirname) + const examples = files + .filter(file => + file !== 'all.js' && + file !== 'init.js' && + file.endsWith('.js')) + .map(file => require(`${__dirname}/${file}`)) + + console.log('Running all node-vault examples...') + + let initData + try { + initData = await init(vault) + } catch (err) { + console.error(err) + } + + await runExamples(examples, vault) + initData && + console.log(`\n\n\nSet this variable to run more examples in the future: + + export VAULT_TOKEN='${initData.root_token}'`) +} + +run().catch(console.error) diff --git a/examples/audits.js b/examples/audits.js new file mode 100644 index 0000000..d1e90b6 --- /dev/null +++ b/examples/audits.js @@ -0,0 +1,17 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() +const path = '/tmp/logs/test.log' + +const example = async (vault) => { + if ((await vault.audits()).hasOwnProperty('testlog/')) return undefined + await vault.enableAudit({ name: 'testlog', type: 'file', options: { path } }) + await vault.write('secret/hello', { value: 'world', lease: '1s' }) + await vault.read('secret/hello') + await vault.delete('secret/hello') + await vault.disableAudit({ name: 'testlog' }) +} + +module.exports = example + +if (require.main === module) example(vault).catch(console.error) diff --git a/examples/auth.js b/examples/auth.js new file mode 100644 index 0000000..d3c5b8d --- /dev/null +++ b/examples/auth.js @@ -0,0 +1,15 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const options = { + requestOptions: { + followAllRedirects: true + } +} + +const example = (vault) => vault.auths(options) + +module.exports = example + +if (require.main === module) example(vault).then(console.log).catch(console.error) diff --git a/examples/auth_approle.js b/examples/auth_approle.js new file mode 100644 index 0000000..4998744 --- /dev/null +++ b/examples/auth_approle.js @@ -0,0 +1,26 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() +const mountPoint = 'approle' +const roleName = 'test-role' + +const example = async (vault) => { + if ((await vault.auths()).hasOwnProperty('approle/')) return undefined + await vault.enableAuth({ + mount_point: mountPoint, + type: 'approle', + description: 'Approle auth' + }) + + await vault.addApproleRole({ role_name: roleName, policies: 'dev-policy, test-policy' }) + const result = + await Promise.all([vault.getApproleRoleId({ role_name: roleName }), + vault.getApproleRoleSecret({ role_name: roleName })]) + const roleId = result[0].data.role_id + const secretId = result[1].data.secret_id + return vault.approleLogin({ role_id: roleId, secret_id: secretId }) +} + +module.exports = example + +if (require.main === module) example(vault).then(console.log).catch(console.error) diff --git a/examples/auth_github.js b/examples/auth_github.js new file mode 100644 index 0000000..8196555 --- /dev/null +++ b/examples/auth_github.js @@ -0,0 +1,24 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const org = process.env.GITHUB_ORG +const team = process.env.GITHUB_TEAM || 'owners' +const token = process.env.GITHUB_TOKEN +const mountPoint = 'github' + +const example = async (vault) => { + if ((await vault.auths()).hasOwnProperty('github/')) return undefined + await vault.enableAuth({ + mount_point: mountPoint, + type: 'github', + description: 'GitHub auth' + }) + await vault.write('auth/github/config', { organization: org }) + await vault.write(`auth/github/map/teams/${team}`, { value: 'root' }) + return vault.githubLogin({ token }) +} + +module.exports = example + +if (require.main === module) example(vault).then(console.log).catch(console.error) diff --git a/examples/auth_ldap.js b/examples/auth_ldap.js new file mode 100644 index 0000000..387a7b2 --- /dev/null +++ b/examples/auth_ldap.js @@ -0,0 +1,21 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode +const vault = require('./../src/main')() + +const mountPoint = 'auth' +const username = 'me' +const password = 'foo' + +const example = async (vault) => { + if ((await vault.auths()).hasOwnProperty('ldap/')) return undefined + await vault.enableAuth({ + mount_point: mountPoint, + type: 'ldap', + description: 'ldap auth' + }) + await vault.write(`auth/ldap/users/${username}`, { password, policies: 'root' }) + return vault.ldapLogin({ username, password }) +} + +module.exports = example + +if (require.main === module) example(vault).then(console.log).catch(console.error) diff --git a/examples/auth_userpass.js b/examples/auth_userpass.js new file mode 100644 index 0000000..1951640 --- /dev/null +++ b/examples/auth_userpass.js @@ -0,0 +1,22 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const mountPoint = 'userpass' +const username = 'me' +const password = 'foo' + +const example = async (vault) => { + if ((await vault.auths()).hasOwnProperty('userpass/')) return undefined + await vault.enableAuth({ + mount_point: mountPoint, + type: 'userpass', + description: 'userpass auth' + }) + await vault.write(`auth/userpass/users/${username}`, { password, policies: 'root' }) + return vault.userpassLogin({ username, password }) +} + +module.exports = example + +if (require.main === module) example(vault).then(console.log).catch(console.error) diff --git a/example/config.hcl b/examples/config.hcl similarity index 100% rename from example/config.hcl rename to examples/config.hcl diff --git a/examples/health.js b/examples/health.js new file mode 100644 index 0000000..6edac8f --- /dev/null +++ b/examples/health.js @@ -0,0 +1,9 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main.js')() + +const example = (vault) => vault.health() + +module.exports = example + +if (require.main === module) example(vault).then(console.log).catch(console.error) diff --git a/examples/help.js b/examples/help.js new file mode 100644 index 0000000..bfe3464 --- /dev/null +++ b/examples/help.js @@ -0,0 +1,9 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main.js')() + +const example = (vault) => vault.help('sys/policy') + +module.exports = example + +if (require.main === module) example(vault).then(console.log).catch(console.error) diff --git a/examples/init.js b/examples/init.js new file mode 100644 index 0000000..bdeb96a --- /dev/null +++ b/examples/init.js @@ -0,0 +1,17 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const example = async (vault) => { + console.log(await vault.initialized()) + const result = await vault.init({ secret_shares: 1, secret_threshold: 1 }) + console.log(result) + vault.login(result.root_token) + const key = result.keys[0] + console.log(await vault.unseal({ secret_shares: 1, key })) + return result +} + +module.exports = example + +if (require.main === module) example(vault).catch(console.error) diff --git a/examples/leases.js b/examples/leases.js new file mode 100644 index 0000000..0a8fe1b --- /dev/null +++ b/examples/leases.js @@ -0,0 +1,17 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +// TODO fix example for leases because generic backend does not generate a lease_id anymore +// See: https://github.com/hashicorp/vault/issues/877 + +const example = async (vault) => { + await vault.write('secret/hello', { value: 'world', lease: '10h' }) + const result = await vault.read('secret/hello') + await vault.revoke({ lease_id: result.lease_id }) + await vault.revokePrefix({ path_prefix: 'secret' }) +} + +module.exports = example + +if (require.main === module) example(vault).catch(console.error) diff --git a/examples/mount_postgresql.js b/examples/mount_postgresql.js new file mode 100644 index 0000000..3c2e173 --- /dev/null +++ b/examples/mount_postgresql.js @@ -0,0 +1,36 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const connection = 'postgresql://root:test@postgres:5432/postgres?sslmode=disable' + +const query = "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID " + +"UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" + +const configure = async () => { + await vault.write('postgresql/config/lease', { lease: '1h', lease_max: '24h' }) + await vault.write('postgresql/config/connection', { value: connection }) +} + +const createRole = () => vault.write('postgresql/roles/readonly', { sql: query }) +const getCredentials = () => vault.read('postgresql/creds/readonly') + +const run = async () => { + await configure() + await createRole() + console.log(await getCredentials()) +} + +const example = async (vault) => { + if ((await vault.mounts()).hasOwnProperty('postgresql/')) return run() + await vault.mount({ + mount_point: 'postgresql', + type: 'postgresql', + description: 'postgresql mount test' + }) + await run() +} + +module.exports = example + +if (require.main === module) example(vault).catch(console.error) diff --git a/examples/pass_request_options.js b/examples/pass_request_options.js new file mode 100644 index 0000000..a04f453 --- /dev/null +++ b/examples/pass_request_options.js @@ -0,0 +1,24 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const options = { + headers: { + 'X-HELLO': 'world' + }, + agentOptions: { + cert: 'mycert', + key: 'mykey', + passphrase: 'password', + securityOptions: 'SSL_OP_NO_SSLv3' + } +} + +const example = async (vault) => { + await vault.help('sys/policy', options) + await vault.help('sys/mounts') +} + +module.exports = example + +if (require.main === module) example(vault).catch(console.error) diff --git a/examples/policies.js b/examples/policies.js new file mode 100644 index 0000000..1dc38a1 --- /dev/null +++ b/examples/policies.js @@ -0,0 +1,18 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const example = async (vault) => { + console.log(await vault.policies()) + await vault.addPolicy({ + name: 'mypolicy', + rules: '{ "path": { "secret/*": { "policy": "write" } } }' + }) + await vault.getPolicy({ name: 'mypolicy' }) + console.log(await vault.policies()) + return vault.removePolicy({ name: 'mypolicy' }) +} + +module.exports = example + +if (require.main === module) example(vault).catch(console.error) diff --git a/examples/rotate.js b/examples/rotate.js new file mode 100644 index 0000000..8b77999 --- /dev/null +++ b/examples/rotate.js @@ -0,0 +1,9 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const example = (vault) => vault.rotate() + +module.exports = example + +if (require.main === module) example(vault).catch(console.error) diff --git a/examples/secret_mounts.js b/examples/secret_mounts.js new file mode 100644 index 0000000..0d5c20d --- /dev/null +++ b/examples/secret_mounts.js @@ -0,0 +1,16 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const example = async (vault) => { + await vault.mounts() + await vault.mount({ mount_point: 'test', type: 'generic', description: 'just a test' }) + await vault.write('test/hello', { value: 'world', lease: '1s' }) + await vault.remount({ from: 'test', to: 'test2' }) + console.log(await vault.read('test2/hello')) + await vault.unmount({ mount_point: 'test2' }) +} + +module.exports = example + +if (require.main === module) example(vault).catch(console.error) diff --git a/examples/status.js b/examples/status.js new file mode 100644 index 0000000..b11f5c1 --- /dev/null +++ b/examples/status.js @@ -0,0 +1,9 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const example = (vault) => vault.status() + +module.exports = example + +if (require.main === module) example(vault).then(console.log).catch(console.error) diff --git a/examples/token.js b/examples/token.js new file mode 100644 index 0000000..8f06d83 --- /dev/null +++ b/examples/token.js @@ -0,0 +1,15 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const example = async (vault) => { + const result = await vault.tokenCreate() + console.log(result) + const newToken = result.auth + await vault.tokenLookup({ token: newToken.client_token }) + await vault.tokenLookupAccessor({ accessor: newToken.accessor }) +} + +module.exports = example + +if (require.main === module) example(vault).then(console.log).catch(console.error) diff --git a/examples/write_read_delete.js b/examples/write_read_delete.js new file mode 100644 index 0000000..569b1d1 --- /dev/null +++ b/examples/write_read_delete.js @@ -0,0 +1,13 @@ +process.env.DEBUG = 'node-vault' // switch on debug mode + +const vault = require('./../src/main')() + +const example = async (vault) => { + await vault.write('secret/hello', { value: 'world', lease: '1s' }) + await vault.read('secret/hello') + await vault.delete('secret/hello') +} + +module.exports = example + +if (require.main === module) example(vault).catch(console.error) diff --git a/features.md b/features.md index 68af6cf..13d78e4 100644 --- a/features.md +++ b/features.md @@ -1,332 +1,591 @@ -# Supported node-vault features +# Supported Vault features - This is a generated list of Vault features supported by node-vault. + This is a generated list of Vault operations supported by node-vault. -## vault.status +## vault.help(path) + +`GET ?help=1` + +Look up the help for a path. + +All endpoints in Vault from system paths, secret paths, and credential +providers provide built-in help. This command looks up and outputs that +help. + +The command requires that the vault be unsealed, because otherwise +the mount points of the backends are unknown. + + +## vault.read(path) + +`GET ` + +Read data from Vault. + +Reads data at the given path from Vault. This can be used to read +secrets and configuration as well as generate dynamic values from +materialized backends. Please reference the documentation for the +backends in use to determine key structure. + + +## vault.write(path) + +`PUT ` + +Write data (secrets or configuration) into Vault. + +Write sends data into Vault at the given path. The behavior of the write is +determined by the backend at the given path. For example, writing to +"aws/policy/ops" will create an "ops" IAM policy for the AWS backend +(configuration), but writing to "consul/foo" will write a value directly into +Consul at that key. Check the documentation of the logical backend you're +using for more information on key structure. + +Data is sent via additional arguments in "key=value" pairs. If value begins +with an "@", then it is loaded from a file. Write expects data in the file to +be in JSON format. If you want to start the value with a literal "@", then +prefix the "@" with a slash: "\@". + + +## vault.list(path) + +`LIST ` + +List data from Vault. + +Retrieve a listing of available data. The data returned, if any, is backend- +and endpoint-specific. + + +## vault.delete(path) + +`DELETE ` + +Delete data (secrets or configuration) from Vault. + +Delete sends a delete operation request to the given path. The +behavior of the delete is determined by the backend at the given +path. For example, deleting "aws/policy/ops" will delete the "ops" +policy for the AWS backend. Use "vault help" for more details on +whether delete is supported for a path and what the behavior is. + + +## vault.status() `GET /sys/seal-status` +Returns the seal status of the Vault. This is an unauthenticated endpoint. -## vault.initialized + +## vault.initialized() `GET /sys/init` +Returns the initialization status of the Vault. + -## vault.init +## vault.init() `PUT /sys/init` +Initializes a new vault. + -## vault.unseal +## vault.unseal() `PUT /sys/unseal` +Unseals the Vault. -## vault.seal + +## vault.seal() `PUT /sys/seal` +Seals the Vault. + -## vault.generateRootStatus +## vault.generateRootStatus() `GET /sys/generate-root/attempt` +Reads the configuration and progress of the current root generation attempt. -## vault.generateRootInit + +## vault.generateRootInit() `PUT /sys/generate-root/attempt` +Initializes a new root generation attempt. Only a single root generation attempt can take place at a time. One (and only one) of otp or pgp_key are required. + -## vault.generateRootCancel +## vault.generateRootCancel() `DELETE /sys/generate-root/attempt` +Cancels any in-progress root generation attempt. This clears any progress made. This must be called to change the OTP or PGP key being used. -## vault.generateRootUpdate + +## vault.generateRootUpdate() `PUT /sys/generate-root/update` +TODO: add description :S + -## vault.mounts +## vault.mounts() `GET /sys/mounts` +Lists all the mounted secret backends. -## vault.mount + +## vault.mount() `POST /sys/mounts/{{mount_point}}` +Mount a new secret backend to the mount point in the URL. + -## vault.unmount +## vault.unmount() `DELETE /sys/mounts/{{mount_point}}` +Unmount the specified mount point. -## vault.remount + +## vault.remount() `POST /sys/remount` +Changes the mount point of an already-mounted backend. -## vault.policies +### PARAMETERS -`GET /sys/policy` + from (string) + The previous mount point. + to (string) + The new mount point. -## vault.addPolicy -`PUT /sys/policy/{{name}}` +## vault.policies() +`GET /sys/policy` -## vault.getPolicy +List the names of the configured access control policies. + + +## vault.getPolicy() `GET /sys/policy/{{name}}` +Retrieve the rules for the named policy. + -## vault.removePolicy +## vault.addPolicy() + +`PUT /sys/policy/{{name}}` + +Add or update a policy. + + +## vault.removePolicy() `DELETE /sys/policy/{{name}}` +Delete the policy with the given name. + -## vault.auths +## vault.auths() `GET /sys/auth` +List the currently enabled credential backends: the name, the type of the backend, and a user friendly description of the purpose for the credential backend. + -## vault.enableAuth +## vault.enableAuth() `POST /sys/auth/{{mount_point}}` +Enable a new auth backend. -## vault.disableAuth + +## vault.disableAuth() `DELETE /sys/auth/{{mount_point}}` +Disable the auth backend at the given mount point. + -## vault.audits +## vault.audits() `GET /sys/audit` +List the currently enabled audit backends. -## vault.enableAudit + +## vault.enableAudit() `PUT /sys/audit/{{name}}` +Enable an audit backend at the given path. + -## vault.disableAudit +## vault.disableAudit() `DELETE /sys/audit/{{name}}` +Disable the given audit backend. -## vault.renew + +## vault.renew() `PUT /sys/leases/renew` +Renew a lease on a secret. + +### PARAMETERS + + increment (duration (sec)) + The desired increment in seconds to the lease. -## vault.revoke + lease_id (string) + The lease identifier to renew. This is included with a lease. + + url_lease_id (string) + The lease identifier to renew. This is included with a lease. + +### DESCRIPTION + +When a secret is read, it may optionally include a lease interval +and a boolean indicating if renew is possible. For secrets that support +lease renewal, this endpoint is used to extend the validity of the +lease and to prevent an automatic revocation. + + +## vault.revoke() `PUT /sys/leases/revoke` +Revoke a leased secret immediately + +### PARAMETERS + + lease_id (string) + The lease identifier to renew. This is included with a lease. + + url_lease_id (string) + The lease identifier to renew. This is included with a lease. -## vault.revokePrefix +### DESCRIPTION + +When a secret is generated with a lease, it is automatically revoked +at the end of the lease period if not renewed. However, in some cases +you may want to force an immediate revocation. This endpoint can be +used to revoke the secret with the given Lease ID. + + +## vault.revokePrefix() `PUT /sys/revoke-prefix/{{path_prefix}}` +TODO: add description :S + -## vault.rotate +## vault.rotate() `PUT /sys/rotate` +Rotates the backend encryption key used to persist data. + + +### DESCRIPTION + +Rotate generates a new encryption key which is used to encrypt all +data going to the storage backend. The old encryption keys are kept so +that data encrypted using those keys can still be decrypted. -## vault.unwrap + +## vault.unwrap() `POST /sys/wrapping/unwrap` +Unwraps a response-wrapped token. + +### PARAMETERS + + token (string) + The unwrap token. + +### DESCRIPTION + +Unwraps a response-wrapped token. Unlike simply reading from cubbyhole/response, +this provides additional validation on the token, and rather than a JSON-escaped +string, the returned response is the exact same as the contained wrapped response. + + +## vault.githubLogin() + +`POST /auth/{{mount_point=github}}/login` -## vault.githubLogin +TODO: add description :S -`POST /auth/{{mount_point}}{{^mount_point}}github{{/mount_point}}/login` +## vault.userpassLogin() -## vault.userpassLogin +`POST /auth/{{mount_point=userpass}}/login/{{username}}` -`POST /auth/{{mount_point}}{{^mount_point}}userpass{{/mount_point}}/login/{{username}}` +TODO: add description :S -## vault.ldapLogin +## vault.ldapLogin() -`POST /auth/{{mount_point}}{{^mount_point}}ldap{{/mount_point}}/login/{{username}}` +`POST /auth/{{mount_point=ldap}}/login/{{username}}` +TODO: add description :S -## vault.oktaLogin -`POST /auth/{{mount_point}}{{^mount_point}}okta{{/mount_point}}/login/{{username}}` +## vault.oktaLogin() +`POST /auth/{{mount_point=okta}}/login/{{username}}` -## vault.radiusLogin +TODO: add description :S -`POST /auth/{{mount_point}}{{^mount_point}}radius{{/mount_point}}/login/{{username}}` +## vault.radiusLogin() -## vault.tokenAccessors +`POST /auth/{{mount_point=radius}}/login/{{username}}` + +TODO: add description :S + + +## vault.tokenAccessors() `LIST /auth/token/accessors` +TODO: add description :S + -## vault.tokenCreate +## vault.tokenCreate() `POST /auth/token/create` +TODO: add description :S -## vault.tokenCreateOrphan + +## vault.tokenCreateOrphan() `POST /auth/token/create-orphan` +TODO: add description :S + -## vault.tokenCreateRole +## vault.tokenCreateRole() `POST /auth/token/create/{{role_name}}` +TODO: add description :S + -## vault.tokenLookup +## vault.tokenLookup() `POST /auth/token/lookup` +TODO: add description :S -## vault.tokenLookupAccessor + +## vault.tokenLookupAccessor() `POST /auth/token/lookup-accessor` +TODO: add description :S + -## vault.tokenLookupSelf +## vault.tokenLookupSelf() `GET /auth/token/lookup-self` +TODO: add description :S -## vault.tokenRenew + +## vault.tokenRenew() `POST /auth/token/renew` +TODO: add description :S + -## vault.tokenRenewSelf +## vault.tokenRenewSelf() `POST /auth/token/renew-self` +TODO: add description :S -## vault.tokenRevoke + +## vault.tokenRevoke() `POST /auth/token/revoke` +TODO: add description :S + -## vault.tokenRevokeAccessor +## vault.tokenRevokeAccessor() `POST /auth/token/revoke-accessor` +TODO: add description :S -## vault.tokenRevokeOrphan + +## vault.tokenRevokeOrphan() `POST /auth/token/revoke-orphan` +TODO: add description :S + -## vault.tokenRevokeSelf +## vault.tokenRevokeSelf() `POST /auth/token/revoke-self` +TODO: add description :S -## vault.tokenRoles + +## vault.tokenRoles() `GET /auth/token/roles?list=true` +TODO: add description :S + -## vault.addTokenRole +## vault.addTokenRole() `POST /auth/token/roles/{{role_name}}` +TODO: add description :S -## vault.getTokenRole + +## vault.getTokenRole() `GET /auth/token/roles/{{role_name}}` +TODO: add description :S + -## vault.removeTokenRole +## vault.removeTokenRole() `DELETE /auth/token/roles/{{role_name}}` +TODO: add description :S + + +## vault.approleRoles() + +`LIST /auth/{{mount_point=approle}}/role` -## vault.approleRoles +TODO: add description :S -`LIST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role` +## vault.addApproleRole() -## vault.addApproleRole +`POST /auth/{{mount_point=approle}}/role/{{role_name}}` -`POST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}` +TODO: add description :S -## vault.getApproleRole +## vault.getApproleRole() -`GET /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}` +`GET /auth/{{mount_point=approle}}/role/{{role_name}}` +TODO: add description :S -## vault.deleteApproleRole -`DELETE /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}` +## vault.deleteApproleRole() +`DELETE /auth/{{mount_point=approle}}/role/{{role_name}}` -## vault.getApproleRoleId +TODO: add description :S -`GET /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/role-id` +## vault.getApproleRoleId() -## vault.updateApproleRoleId +`GET /auth/{{mount_point=approle}}/role/{{role_name}}/role-id` -`POST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/role-id` +TODO: add description :S -## vault.getApproleRoleSecret +## vault.updateApproleRoleId() -`POST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/secret-id` +`POST /auth/{{mount_point=approle}}/role/{{role_name}}/role-id` +TODO: add description :S -## vault.approleSecretAccessors -`LIST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/secret-id` +## vault.getApproleRoleSecret() +`POST /auth/{{mount_point=approle}}/role/{{role_name}}/secret-id` -## vault.approleSecretLookup +TODO: add description :S -`POST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/secret-id/lookup` +## vault.approleSecretAccessors() -## vault.approleSecretDestroy +`LIST /auth/{{mount_point=approle}}/role/{{role_name}}/secret-id` -`POST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/secret-id/destroy` +TODO: add description :S -## vault.approleSecretAccessorLookup +## vault.approleSecretLookup() -`POST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/secret-id-accessor/lookup` +`POST /auth/{{mount_point=approle}}/role/{{role_name}}/secret-id/lookup` +TODO: add description :S -## vault.approleSecretAccessorDestroy -`POST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/secret-id-accessor/destroy` +## vault.approleSecretDestroy() +`POST /auth/{{mount_point=approle}}/role/{{role_name}}/secret-id/destroy` -## vault.approleLogin +TODO: add description :S -`POST /auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/login` +## vault.approleSecretAccessorLookup() -## vault.health +`POST /auth/{{mount_point=approle}}/role/{{role_name}}/secret-id-accessor/lookup` + +TODO: add description :S + + +## vault.approleSecretAccessorDestroy() + +`POST /auth/{{mount_point=approle}}/role/{{role_name}}/secret-id-accessor/destroy` + +TODO: add description :S + + +## vault.approleLogin() + +`POST /auth/{{mount_point=approle}}/login` + +TODO: add description :S + + +## vault.health() `GET /sys/health` +TODO: add description :S -## vault.leader + +## vault.leader() `GET /sys/leader` +TODO: add description :S + -## vault.stepDown +## vault.stepDown() `PUT /sys/step-down` + +TODO: add description :S diff --git a/package.json b/package.json index c13fd37..639c44c 100644 --- a/package.json +++ b/package.json @@ -1,50 +1,50 @@ { "name": "node-vault", "version": "0.8.0", - "description": "Javascript client for HashiCorp's Vault", - "main": "./src/index.js", + "description": "NodeJS API client for HashiCorp's Vault", + "main": "./src/main.js", "scripts": { - "precoverage": "npm run lint", - "coverage": "istanbul cover --report text-summary node_modules/.bin/_mocha", - "lint": "eslint .", + "lint": "standard", "test": "mocha", + "coverage": "nyc --reporter text-summary mocha", + "nsp": "nsp check", + "complete-test": "yarn lint && yarn coverage", + "docker-test": "docker-compose build && docker-compose up --force-recreate test", "test-unit": "mocha test/unit.js", "test-watch": "mocha --watch", "predocs": "node scripts/write-features.js", - "docs": "docco --output docs src/*.js", - "nsp": "nsp check", - "prepublish": "npm run nsp", - "precommit": "node scripts/write-features.js && git add features.md" + "docs": "docco --output docs src/**/*.js src/*.js", + "prepublishOnly": "yarn nsp", + "precommit": "node scripts/write-features.js && git add features.md", + "refresh-docker-vault": "docker-compose up --force-recreate vault", + "examples": "node examples/all" }, "directories": { - "example": "./example", - "doc": "./docs" + "example": "./examples", + "doc": "./docs", + "test": "./test", + "lib": "src" }, "files": [ "src" ], "dependencies": { "debug": "3.1.0", - "mustache": "^2.2.1", "request": "^2.83.0", "request-promise-native": "^1.0.5", "tv4": "^1.2.7" }, "devDependencies": { - "chai": "^3.5.0", - "dirty-chai": "^1.2.2", - "docco": "^0.7.0", - "eslint": "2.13.1", - "eslint-config-airbnb": "^9.0.1", - "eslint-plugin-import": "^1.11.1", - "eslint-plugin-jsx-a11y": "1.2.0", - "eslint-plugin-react": "^5.2.2", - "husky": "^0.14.3", - "istanbul": "^0.4.5", - "mocha": "2.4.5", - "nsp": "^2.6.3", - "sinon": "1.17.3", - "sinon-chai": "^2.8.0" + "chai": "^4.1.2", + "dirty-chai": "^2.0.1", + "docco": "^0.8.0", + "fs-extra": "^5.0.0", + "mocha": "^4.1.0", + "nsp": "^3.1.0", + "nyc": "^11.4.1", + "sinon": "^4.1.3", + "sinon-chai": "^2.8.0", + "standard": "^10.0.3" }, "repository": { "type": "git", @@ -63,7 +63,8 @@ "Trevor Robinson (https://github.com/trevorr)", "Tim Robinson (https://github.com/timjrobinson)", "Adam Kelsall (https://github.com/adamkelsall)", - "Charles Phillips (https://github.com/doublerebel)" + "Charles Phillips (https://github.com/doublerebel)", + "Dani Guardiola (https://github.com/daniguardiola)" ], "license": "MIT", "bugs": { diff --git a/scripts/write-features.js b/scripts/write-features.js index d4019ab..b20b4e2 100644 --- a/scripts/write-features.js +++ b/scripts/write-features.js @@ -1,17 +1,36 @@ -const fs = require('fs'); -const commands = require('../src/commands'); +const fs = require('fs-extra') +const features = require('../src/interface/features') +const resourceMethods = require('../src/interface/resource-methods') -const result = Object.keys(commands).map(name => { - const command = commands[name]; +const refreshFeatures = () => { + const featuresDoc = Object.keys(features).map(name => { + const feature = features[name] - return ` -## vault.${name} + return ` +## vault.${name}() -\`${command.method} ${command.path}\` -`; -}); +\`${feature.method} ${feature.path}\` -result.unshift(`# Supported node-vault features +${feature.description || 'TODO: add description :S'} +` + }) - This is a generated list of Vault features supported by node-vault.`); -fs.writeFileSync('./features.md', result.join('\n')); + const resourceMethodsDoc = resourceMethods.map(method => { + return ` +## vault.${method.name}(path) + +\`${method.operation} ${method.query || ''}\` + +${method.description || 'TODO: add description :S'} +` + }) + + const result = [...resourceMethodsDoc, ...featuresDoc] + + result.unshift(`# Supported Vault features + + This is a generated list of Vault operations supported by node-vault.`) + return fs.writeFile('./features.md', result.join('\n')) +} + +refreshFeatures() diff --git a/src/commands.js b/src/commands.js deleted file mode 100644 index 1eb70aa..0000000 --- a/src/commands.js +++ /dev/null @@ -1,1164 +0,0 @@ -const sealStatusResponse = { - type: 'object', - properties: { - sealed: { - type: 'boolean', - }, - t: { - type: 'integer', - }, - n: { - type: 'integer', - }, - progress: { - type: 'integer', - }, - }, - required: ['sealed', 't', 'n', 'progress'], -}; - -const auth = { - type: 'object', - properties: { - client_token: { - type: 'string', - }, - policies: { - type: 'array', - items: { - type: 'string', - }, - }, - metadata: { - type: 'object', - }, - lease_duration: { - type: 'integer', - }, - renewable: { - type: 'boolean', - }, - }, -}; - -const tokenResponse = { - type: 'object', - properties: { - auth, - }, - required: ['auth'], -}; - -const approleResponse = { - type: 'object', - properties: { - auth, - warnings: { - type: 'string', - }, - wrap_info: { - type: 'string', - }, - data: { - type: 'object', - }, - lease_duration: { - type: 'integer', - }, - renewable: { - type: 'boolean', - }, - lease_id: { - type: 'string', - }, - }, -}; - -module.exports = { - status: { - method: 'GET', - path: '/sys/seal-status', - schema: { - res: sealStatusResponse, - }, - }, - initialized: { - method: 'GET', - path: '/sys/init', - }, - init: { - method: 'PUT', - path: '/sys/init', - schema: { - req: { - type: 'object', - properties: { - secret_shares: { - type: 'integer', - minimum: 1, - }, - secret_threshold: { - type: 'integer', - minimum: 1, - }, - pgp_keys: { - type: 'array', - items: { - type: 'string', - }, - uniqueItems: true, - }, - }, - required: ['secret_shares', 'secret_threshold'], - }, - res: { - type: 'object', - properties: { - keys: { - type: 'array', - items: { - type: 'string', - }, - uniqueItems: true, - }, - root_token: { - type: 'string', - }, - }, - required: ['keys', 'root_token'], - }, - }, - }, - unseal: { - method: 'PUT', - path: '/sys/unseal', - schema: { - res: sealStatusResponse, - }, - }, - seal: { - method: 'PUT', - path: '/sys/seal', - }, - generateRootStatus: { - method: 'GET', - path: '/sys/generate-root/attempt', - schema: { - res: { - type: 'object', - properties: { - started: { - type: 'boolean', - }, - nonce: { - type: 'string', - }, - progress: { - type: 'integer', - minimum: 0, - }, - required: { - type: 'integer', - minimum: 1, - }, - pgp_fingerprint: { - type: 'string', - }, - complete: { - type: 'boolean', - }, - }, - required: ['started', 'nonce', 'progress', 'required', 'pgp_fingerprint', 'complete'], - }, - }, - }, - generateRootInit: { - method: 'PUT', - path: '/sys/generate-root/attempt', - schema: { - req: { - type: 'object', - properties: { - otp: { - type: 'string', - }, - pgp_key: { - type: 'string', - }, - }, - }, - res: { - type: 'object', - properties: { - started: { - type: 'boolean', - }, - nonce: { - type: 'string', - }, - progress: { - type: 'integer', - minimum: 0, - }, - required: { - type: 'integer', - minimum: 1, - }, - pgp_fingerprint: { - type: 'string', - }, - complete: { - type: 'boolean', - }, - }, - required: ['started', 'nonce', 'progress', 'required', 'pgp_fingerprint', 'complete'], - }, - }, - }, - generateRootCancel: { - method: 'DELETE', - path: '/sys/generate-root/attempt', - }, - generateRootUpdate: { - method: 'PUT', - path: '/sys/generate-root/update', - schema: { - req: { - type: 'object', - properties: { - key: { - type: 'string', - }, - nonce: { - type: 'string', - }, - }, - required: ['key', 'nonce'], - }, - res: { - type: 'object', - properties: { - started: { - type: 'boolean', - }, - nonce: { - type: 'string', - }, - progress: { - type: 'integer', - minimum: 0, - }, - required: { - type: 'integer', - minimum: 1, - }, - pgp_fingerprint: { - type: 'string', - }, - complete: { - type: 'boolean', - }, - encoded_root_token: { - type: 'string', - }, - }, - required: ['started', 'nonce', 'progress', 'required', 'pgp_fingerprint', 'complete'], - }, - }, - }, - mounts: { - method: 'GET', - path: '/sys/mounts', - }, - mount: { - method: 'POST', - path: '/sys/mounts/{{mount_point}}', - }, - unmount: { - method: 'DELETE', - path: '/sys/mounts/{{mount_point}}', - }, - remount: { - method: 'POST', - path: '/sys/remount', - }, - policies: { - method: 'GET', - path: '/sys/policy', - }, - addPolicy: { - method: 'PUT', - path: '/sys/policy/{{name}}', - }, - getPolicy: { - method: 'GET', - path: '/sys/policy/{{name}}', - }, - removePolicy: { - method: 'DELETE', - path: '/sys/policy/{{name}}', - }, - auths: { - method: 'GET', - path: '/sys/auth', - }, - enableAuth: { - method: 'POST', - path: '/sys/auth/{{mount_point}}', - }, - disableAuth: { - method: 'DELETE', - path: '/sys/auth/{{mount_point}}', - }, - audits: { - method: 'GET', - path: '/sys/audit', - }, - enableAudit: { - method: 'PUT', - path: '/sys/audit/{{name}}', - }, - disableAudit: { - method: 'DELETE', - path: '/sys/audit/{{name}}', - }, - renew: { - method: 'PUT', - path: '/sys/leases/renew', - schema: { - req: { - type: 'object', - properties: { - lease_id: { - type: 'string', - }, - increment: { - type: 'integer', - }, - }, - required: ['lease_id'], - }, - res: { - type: 'object', - properties: { - lease_id: { - type: 'string', - }, - renewable: { - type: 'boolean', - }, - lease_duration: { - type: 'integer', - }, - }, - }, - }, - }, - revoke: { - method: 'PUT', - path: '/sys/leases/revoke', - schema: { - req: { - type: 'object', - properties: { - lease_id: { - type: 'string', - }, - }, - required: ['lease_id'], - }, - }, - }, - revokePrefix: { - method: 'PUT', - path: '/sys/revoke-prefix/{{path_prefix}}', - }, - rotate: { - method: 'PUT', - path: '/sys/rotate', - }, - unwrap: { - method: 'POST', - path: '/sys/wrapping/unwrap', - schema: { - req: { - type: 'object', - properties: { - token: { - type: 'string', - }, - }, - }, - }, - }, - githubLogin: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}github{{/mount_point}}/login', - schema: { - req: { - type: 'object', - properties: { - token: { - type: 'string', - }, - }, - required: ['token'], - }, - res: tokenResponse, - }, - }, - userpassLogin: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}userpass{{/mount_point}}/login/{{username}}', - schema: { - req: { - type: 'object', - properties: { - password: { - type: 'string', - }, - }, - required: ['password'], - }, - res: tokenResponse, - }, - }, - ldapLogin: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}ldap{{/mount_point}}/login/{{username}}', - schema: { - req: { - type: 'object', - properties: { - password: { - type: 'string', - }, - }, - required: ['password'], - }, - res: tokenResponse, - }, - }, - oktaLogin: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}okta{{/mount_point}}/login/{{username}}', - schema: { - req: { - type: 'object', - properties: { - password: { - type: 'string', - }, - }, - required: ['password'], - }, - res: tokenResponse, - }, - }, - radiusLogin: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}radius{{/mount_point}}/login/{{username}}', - schema: { - req: { - type: 'object', - properties: { - password: { - type: 'string', - }, - }, - required: ['password'], - }, - res: tokenResponse, - }, - }, - tokenAccessors: { - method: 'LIST', - path: '/auth/token/accessors', - schema: { - res: { - type: 'object', - properties: { - data: { - type: 'object', - properties: { - keys: { - type: 'array', - items: { - type: 'string', - }, - }, - }, - }, - }, - required: ['data'], - }, - }, - }, - tokenCreate: { - method: 'POST', - path: '/auth/token/create', - schema: { - req: { - type: 'object', - properties: { - id: { - type: 'string', - }, - policies: { - type: 'array', - items: { - type: 'string', - }, - }, - meta: { - type: 'object', - }, - no_parent: { - type: 'boolean', - }, - no_default_policy: { - type: 'boolean', - }, - renewable: { - type: 'boolean', - }, - ttl: { - type: 'string', - }, - explicit_max_ttl: { - type: 'string', - }, - display_name: { - type: 'string', - }, - num_uses: { - type: 'integer', - }, - }, - }, - res: tokenResponse, - }, - }, - tokenCreateOrphan: { - method: 'POST', - path: '/auth/token/create-orphan', - schema: { - req: { - type: 'object', - properties: { - id: { - type: 'string', - }, - policies: { - type: 'array', - items: { - type: 'string', - }, - }, - meta: { - type: 'object', - }, - no_parent: { - type: 'boolean', - }, - no_default_policy: { - type: 'boolean', - }, - renewable: { - type: 'boolean', - }, - ttl: { - type: 'string', - }, - explicit_max_ttl: { - type: 'string', - }, - display_name: { - type: 'string', - }, - num_uses: { - type: 'integer', - }, - }, - }, - res: tokenResponse, - }, - }, - tokenCreateRole: { - method: 'POST', - path: '/auth/token/create/{{role_name}}', - schema: { - req: { - type: 'object', - properties: { - id: { - type: 'string', - }, - policies: { - type: 'array', - items: { - type: 'string', - }, - }, - meta: { - type: 'object', - }, - no_parent: { - type: 'boolean', - }, - no_default_policy: { - type: 'boolean', - }, - renewable: { - type: 'boolean', - }, - ttl: { - type: 'string', - }, - explicit_max_ttl: { - type: 'string', - }, - display_name: { - type: 'string', - }, - num_uses: { - type: 'integer', - }, - }, - }, - res: tokenResponse, - }, - }, - tokenLookup: { - method: 'POST', - path: '/auth/token/lookup', - schema: { - req: { - type: 'object', - properties: { - token: { - type: 'string', - }, - }, - required: ['token'], - }, - res: { - type: 'object', - properties: { - data: { - type: 'object', - properties: { - id: { - type: 'string', - }, - policies: { - type: 'array', - items: { - type: 'string', - }, - }, - path: { - type: 'string', - }, - meta: { - type: 'object', - }, - display_name: { - type: 'string', - }, - num_uses: { - type: 'integer', - }, - }, - }, - }, - required: ['data'], - }, - }, - }, - tokenLookupAccessor: { - method: 'POST', - path: '/auth/token/lookup-accessor', - schema: { - req: { - type: 'object', - properties: { - accessor: { - type: 'string', - }, - }, - required: ['accessor'], - }, - res: { - type: 'object', - properties: { - data: { - type: 'object', - properties: { - id: { - type: 'string', - }, - policies: { - type: 'array', - items: { - type: 'string', - }, - }, - path: { - type: 'string', - }, - meta: { - type: 'object', - }, - display_name: { - type: 'string', - }, - num_uses: { - type: 'integer', - }, - }, - }, - }, - required: ['data'], - }, - }, - }, - tokenLookupSelf: { - method: 'GET', - path: '/auth/token/lookup-self', - schema: { - res: { - type: 'object', - properties: { - data: { - type: 'object', - properties: { - id: { - type: 'string', - }, - policies: { - type: 'array', - items: { - type: 'string', - }, - }, - path: { - type: 'string', - }, - meta: { - type: 'object', - }, - display_name: { - type: 'string', - }, - num_uses: { - type: 'integer', - }, - }, - }, - }, - required: ['data'], - }, - }, - }, - tokenRenew: { - method: 'POST', - path: '/auth/token/renew', - schema: { - req: { - type: 'object', - properties: { - token: { - type: 'string', - }, - increment: { - type: ['integer', 'string'], - }, - }, - required: ['token'], - }, - res: tokenResponse, - }, - }, - tokenRenewSelf: { - method: 'POST', - path: '/auth/token/renew-self', - schema: { - req: { - type: 'object', - properties: { - increment: { - type: ['integer', 'string'], - }, - }, - }, - res: tokenResponse, - }, - }, - tokenRevoke: { - method: 'POST', - path: '/auth/token/revoke', - schema: { - req: { - type: 'object', - properties: { - token: { - type: 'string', - }, - }, - required: ['token'], - }, - }, - }, - tokenRevokeAccessor: { - method: 'POST', - path: '/auth/token/revoke-accessor', - schema: { - req: { - type: 'object', - properties: { - accessor: { - type: 'string', - }, - }, - required: ['accessor'], - }, - }, - }, - tokenRevokeOrphan: { - method: 'POST', - path: '/auth/token/revoke-orphan', - schema: { - req: { - type: 'object', - properties: { - token: { - type: 'string', - }, - }, - required: ['token'], - }, - }, - }, - tokenRevokeSelf: { - method: 'POST', - path: '/auth/token/revoke-self', - }, - tokenRoles: { - method: 'GET', - path: '/auth/token/roles?list=true', - schema: { - res: { - type: 'object', - properties: { - data: { - type: 'object', - properties: { - keys: { - type: 'array', - items: { - type: 'string', - }, - }, - }, - }, - }, - required: ['data'], - }, - }, - }, - addTokenRole: { - method: 'POST', - path: '/auth/token/roles/{{role_name}}', - schema: { - req: { - type: 'object', - properties: { - allowed_policies: { - type: 'string', - }, - disallowed_policies: { - type: 'string', - }, - orphan: { - type: 'boolean', - }, - period: { - type: 'integer', - }, - renewable: { - type: 'boolean', - }, - path_suffix: { - type: 'string', - }, - explicit_max_ttl: { - type: 'integer', - }, - }, - }, - }, - }, - getTokenRole: { - method: 'GET', - path: '/auth/token/roles/{{role_name}}', - }, - removeTokenRole: { - method: 'DELETE', - path: '/auth/token/roles/{{role_name}}', - }, - approleRoles: { - method: 'LIST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role', - schema: { - res: approleResponse, - }, - }, - addApproleRole: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}', - schema: { - req: { - bind_secret_id: { - type: 'boolean', - }, - bound_cidr_list: { - type: 'string', - }, - policies: { - type: 'string', - }, - secret_id_num_uses: { - type: 'integer', - }, - secret_id_ttl: { - type: 'integer', - }, - token_num_uses: { - type: 'integer', - }, - token_ttl: { - type: 'integer', - }, - token_max_ttl: { - type: 'integer', - }, - period: { - type: 'integer', - }, - }, - }, - }, - getApproleRole: { - method: 'GET', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}', - schema: { - res: approleResponse, - }, - }, - deleteApproleRole: { - method: 'DELETE', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}', - }, - getApproleRoleId: { - method: 'GET', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/role-id', - schema: { - res: approleResponse, - }, - }, - updateApproleRoleId: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/role/{{role_name}}/role-id', - schema: { - req: { - type: 'object', - properties: { - role_id: { - type: 'string', - }, - }, - required: ['role_id'], - }, - }, - }, - getApproleRoleSecret: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}' + - '/role/{{role_name}}/secret-id', - schema: { - req: { - type: 'object', - properties: { - metadata: { - type: 'string', - }, - cidr_list: { - type: 'array', - items: { - type: 'string', - }, - }, - }, - }, - res: approleResponse, - }, - }, - approleSecretAccessors: { - method: 'LIST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}' + - '/role/{{role_name}}/secret-id', - schema: { - res: approleResponse, - }, - }, - approleSecretLookup: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}' + - '/role/{{role_name}}/secret-id/lookup', - schema: { - req: { - type: 'object', - properties: { - secret_id: { - type: 'string', - }, - }, - required: ['secret_id'], - }, - res: approleResponse, - }, - }, - approleSecretDestroy: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}' + - '/role/{{role_name}}/secret-id/destroy', - schema: { - req: { - type: 'object', - properties: { - secret_id: { - type: 'string', - }, - }, - required: ['secret_id'], - }, - }, - }, - approleSecretAccessorLookup: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}' + - '/role/{{role_name}}/secret-id-accessor/lookup', - schema: { - req: { - type: 'object', - properties: { - secret_id: { - type: 'string', - }, - }, - required: ['secret_id'], - }, - }, - }, - approleSecretAccessorDestroy: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}' + - '/role/{{role_name}}/secret-id-accessor/destroy', - }, - approleLogin: { - method: 'POST', - path: '/auth/{{mount_point}}{{^mount_point}}approle{{/mount_point}}/login', - schema: { - req: { - type: 'object', - properties: { - role_id: { - type: 'string', - }, - secret_id: { - type: 'string', - }, - }, - required: ['role_id', 'secret_id'], - }, - res: approleResponse, - }, - }, - health: { - method: 'GET', - path: '/sys/health', - schema: { - query: { - type: 'object', - properties: { - standbyok: { - type: 'boolean', - }, - activecode: { - type: 'integer', - }, - standbycode: { - type: 'integer', - }, - sealedcode: { - type: 'integer', - }, - uninitcode: { - type: 'integer', - }, - }, - }, - res: { - type: 'object', - properties: { - cluster_id: { - type: 'string', - }, - cluster_name: { - type: 'string', - }, - version: { - type: 'string', - }, - server_time_utc: { - type: 'integer', - }, - standby: { - type: 'boolean', - }, - sealed: { - type: 'boolean', - }, - initialized: { - type: 'boolean', - }, - }, - }, - }, - }, - leader: { - method: 'GET', - path: '/sys/leader', - schema: { - res: { - type: 'object', - properties: { - ha_enabled: { - type: 'boolean', - }, - is_self: { - type: 'boolean', - }, - leader_address: { - type: 'string', - }, - }, - }, - }, - }, - stepDown: { - method: 'PUT', - path: '/sys/step-down', - }, -}; diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 9b6d365..0000000 --- a/src/index.js +++ /dev/null @@ -1,176 +0,0 @@ -'use strict'; - -let debug = require('debug')('node-vault'); -let tv4 = require('tv4'); -let commands = require('./commands.js'); -let mustache = require('mustache'); -let rp = require('request-promise-native'); - -module.exports = (config = {}) => { - // load conditional dependencies - debug = config.debug || debug; - tv4 = config.tv4 || tv4; - commands = config.commands || commands; - mustache = config.mustache || mustache; - rp = (config['request-promise'] || rp).defaults({ - json: true, - resolveWithFullResponse: true, - simple: false, - strictSSL: !process.env.VAULT_SKIP_VERIFY, - }); - const client = {}; - - function handleVaultResponse(response) { - if (!response) return Promise.reject(new Error('No response passed')); - debug(response.statusCode); - if (response.statusCode !== 200 && response.statusCode !== 204) { - // handle health response not as error - if (response.request.path.match(/sys\/health/) !== null) { - return Promise.resolve(response.body); - } - let message; - if (response.body && response.body.errors && response.body.errors.length > 0) { - message = response.body.errors[0]; - } else { - message = `Status ${response.statusCode}`; - } - const error = new Error(message); - return Promise.reject(error); - } - return Promise.resolve(response.body); - } - - client.handleVaultResponse = handleVaultResponse; - - // defaults - client.apiVersion = config.apiVersion || 'v1'; - client.endpoint = config.endpoint || process.env.VAULT_ADDR || 'http://127.0.0.1:8200'; - client.token = config.token || process.env.VAULT_TOKEN; - - const requestSchema = { - type: 'object', - properties: { - path: { - type: 'string', - }, - method: { - type: 'string', - }, - }, - required: ['path', 'method'], - }; - - // Handle any HTTP requests - client.request = (options = {}) => { - const valid = tv4.validate(options, requestSchema); - if (!valid) return Promise.reject(tv4.error); - let uri = `${client.endpoint}/${client.apiVersion}${options.path}`; - // Replace variables in uri. - uri = mustache.render(uri, options.json); - // Replace unicode encodings. - uri = uri.replace(///g, '/'); - options.headers = options.headers || {}; - if (typeof client.token === 'string' && client.token.length) { - options.headers['X-Vault-Token'] = client.token; - } - options.uri = uri; - debug(options.method, uri); - // debug(options.json); - return rp(options).then(handleVaultResponse); - }; - - client.help = (path, requestOptions) => { - debug(`help for ${path}`); - const options = Object.assign({}, config.requestOptions, requestOptions); - options.path = `/${path}?help=1`; - options.method = 'GET'; - return client.request(options); - }; - - client.write = (path, data, requestOptions) => { - debug('write %o to %s', data, path); - const options = Object.assign({}, config.requestOptions, requestOptions); - options.path = `/${path}`; - options.json = data; - options.method = 'PUT'; - return client.request(options); - }; - - client.read = (path, requestOptions) => { - debug(`read ${path}`); - const options = Object.assign({}, config.requestOptions, requestOptions); - options.path = `/${path}`; - options.method = 'GET'; - return client.request(options); - }; - - client.list = (path, requestOptions) => { - debug(`list ${path}`); - const options = Object.assign({}, config.requestOptions, requestOptions); - options.path = `/${path}`; - options.method = 'LIST'; - return client.request(options); - }; - - client.delete = (path, requestOptions) => { - debug(`delete ${path}`); - const options = Object.assign({}, config.requestOptions, requestOptions); - options.path = `/${path}`; - options.method = 'DELETE'; - return client.request(options); - }; - - function validate(json, schema) { - // ignore validation if no schema - if (schema === undefined) return Promise.resolve(); - const valid = tv4.validate(json, schema); - if (!valid) { - debug(tv4.error.dataPath); - debug(tv4.error.message); - return Promise.reject(tv4.error); - } - return Promise.resolve(); - } - - function extendOptions(conf, options) { - const schema = conf.schema.query; - // no schema for the query -> no need to extend - if (!schema) return Promise.resolve(options); - const params = []; - for (const key of Object.keys(schema.properties)) { - if (key in options.json) { - params.push(`${key}=${encodeURIComponent(options.json[key])}`); - } - } - if (params.length > 0) { - options.path += `?${params.join('&')}`; - } - return Promise.resolve(options); - } - - function generateFunction(name, conf) { - client[name] = (args = {}) => { - const options = Object.assign({}, config.requestOptions, args.requestOptions); - options.method = conf.method; - options.path = conf.path; - options.json = args; - // no schema object -> no validation - if (!conf.schema) return client.request(options); - // else do validation of request URL and body - return validate(options.json, conf.schema.req) - .then(() => validate(options.json, conf.schema.query)) - .then(() => extendOptions(conf, options)) - .then((extendedOptions) => client.request(extendedOptions)); - }; - } - - client.generateFunction = generateFunction; - - // protecting global object properties from being added - // enforcing the immutable rule: https://github.com/airbnb/javascript#iterators-and-generators - // going the functional way first defining a wrapper function - const assignFunctions = commandName => generateFunction(commandName, commands[commandName]); - Object.keys(commands).forEach(assignFunctions); - - return client; -}; diff --git a/src/interface/features.js b/src/interface/features.js new file mode 100644 index 0000000..9d8b7ba --- /dev/null +++ b/src/interface/features.js @@ -0,0 +1,1045 @@ +// token and approle response auth validation +const AUTH_SCHEME = { + type: 'object', + properties: { + client_token: { + type: 'string' + }, + policies: { + type: 'array', + items: { + type: 'string' + } + }, + metadata: { + type: 'object' + }, + lease_duration: { + type: 'integer' + }, + renewable: { + type: 'boolean' + } + } +} + +// token operation response validation +const TOKEN_RESPONSE_SCHEME = { + type: 'object', + properties: { + auth: AUTH_SCHEME + }, + required: ['auth'] +} + +// approle response validation +const APPROLE_RESPONSE_SCHEME = { + type: 'object', + properties: { + auth: AUTH_SCHEME, + warnings: { + type: 'string' + }, + wrap_info: { + type: 'string' + }, + data: { + type: 'object' + }, + lease_duration: { + type: 'integer' + }, + renewable: { + type: 'boolean' + }, + lease_id: { + type: 'string' + } + } +} + +// status response validation, also used in unseal +const SEAL_STATUS_RESPONSE = { + type: 'object', + properties: { + sealed: { + type: 'boolean' + }, + t: { + type: 'integer' + }, + n: { + type: 'integer' + }, + progress: { + type: 'integer' + } + }, + required: ['sealed', 't', 'n', 'progress'] +} + +// token creation validation +const TOKEN_CREATE_SCHEME = { + req: { + type: 'object', + properties: { + id: { + type: 'string' + }, + policies: { + type: 'array', + items: { + type: 'string' + } + }, + meta: { + type: 'object' + }, + no_parent: { + type: 'boolean' + }, + no_default_policy: { + type: 'boolean' + }, + renewable: { + type: 'boolean' + }, + ttl: { + type: 'string' + }, + explicit_max_ttl: { + type: 'string' + }, + display_name: { + type: 'string' + }, + num_uses: { + type: 'integer' + } + } + }, + res: TOKEN_RESPONSE_SCHEME +} + +// token lookup response validation +const TOKEN_LOOKUP_RESPONSE_SCHEME = { + type: 'object', + properties: { + data: { + type: 'object', + properties: { + id: { + type: 'string' + }, + policies: { + type: 'array', + items: { + type: 'string' + } + }, + path: { + type: 'string' + }, + meta: { + type: 'object' + }, + display_name: { + type: 'string' + }, + num_uses: { + type: 'integer' + } + } + } + }, + required: ['data'] +} + +// token accessors and roles validation +const TOKEN_ACCESSORS_AND_ROLES_SCHEME = { + res: { + type: 'object', + properties: { + data: { + type: 'object', + properties: { + keys: { + type: 'array', + items: { + type: 'string' + } + } + } + } + }, + required: ['data'] + } +} + +// root operation response validation +const ROOT_RESPONSE_SCHEME = { + type: 'object', + properties: { + started: { + type: 'boolean' + }, + nonce: { + type: 'string' + }, + progress: { + type: 'integer', + minimum: 0 + }, + required: { + type: 'integer', + minimum: 1 + }, + pgp_fingerprint: { + type: 'string' + }, + complete: { + type: 'boolean' + }, + encoded_root_token: { + type: 'string' + } + }, + required: ['started', 'nonce', 'progress', 'required', 'pgp_fingerprint', 'complete'] +} + +const features = { + // lifecycle and status + status: { + method: 'GET', + path: '/sys/seal-status', + description: 'Returns the seal status of the Vault. This is an unauthenticated endpoint.', + schema: { + res: SEAL_STATUS_RESPONSE + } + }, + initialized: { + method: 'GET', + path: '/sys/init', + description: 'Returns the initialization status of the Vault.' + }, + init: { + method: 'PUT', + path: '/sys/init', + description: 'Initializes a new vault.', + todo: 'path-help: POST', + schema: { + req: { + type: 'object', + properties: { + secret_shares: { + type: 'integer', + minimum: 1 + }, + secret_threshold: { + type: 'integer', + minimum: 1 + }, + pgp_keys: { + type: 'array', + items: { + type: 'string' + }, + uniqueItems: true + } + }, + required: ['secret_shares', 'secret_threshold'] + }, + res: { + type: 'object', + properties: { + keys: { + type: 'array', + items: { + type: 'string' + }, + uniqueItems: true + }, + root_token: { + type: 'string' + } + }, + required: ['keys', 'root_token'] + } + } + }, + // seal / unseal vault + unseal: { + method: 'PUT', + path: '/sys/unseal', + description: 'Unseals the Vault.', + schema: { + res: SEAL_STATUS_RESPONSE + } + }, + seal: { + method: 'PUT', + path: '/sys/seal', + description: 'Seals the Vault.' + }, + // root access + generateRootStatus: { + method: 'GET', + path: '/sys/generate-root/attempt', + description: 'Reads the configuration and progress of the current root generation attempt.', + schema: { + res: ROOT_RESPONSE_SCHEME + } + }, + generateRootInit: { + method: 'PUT', + path: '/sys/generate-root/attempt', + todo: 'path-help: POST', + description: 'Initializes a new root generation attempt. Only a single root generation attempt can take place at a time. One (and only one) of otp or pgp_key are required.', + schema: { + req: { + type: 'object', + properties: { + otp: { + type: 'string' + }, + pgp_key: { + type: 'string' + } + } + }, + res: ROOT_RESPONSE_SCHEME + } + }, + generateRootCancel: { + method: 'DELETE', + path: '/sys/generate-root/attempt', + description: 'Cancels any in-progress root generation attempt. This clears any progress made. This must be called to change the OTP or PGP key being used.' + }, + generateRootUpdate: { + method: 'PUT', + path: '/sys/generate-root/update', + todo: 'find / add documentation', + schema: { + req: { + type: 'object', + properties: { + key: { + type: 'string' + }, + nonce: { + type: 'string' + } + }, + required: ['key', 'nonce'] + }, + res: ROOT_RESPONSE_SCHEME + } + }, + // mounts + mounts: { + method: 'GET', + path: '/sys/mounts', + description: 'Lists all the mounted secret backends.' + }, + mount: { + method: 'POST', + path: '/sys/mounts/{{mount_point}}', + description: 'Mount a new secret backend to the mount point in the URL.' + }, + unmount: { + method: 'DELETE', + path: '/sys/mounts/{{mount_point}}', + description: 'Unmount the specified mount point.' + }, + remount: { + method: 'POST', + path: '/sys/remount', + description: ` + +Changes the mount point of an already-mounted backend. + +### PARAMETERS + + from (string) + The previous mount point. + + to (string) + The new mount point. + + `.trim() + }, + // policies + policies: { + method: 'GET', + path: '/sys/policy', + description: 'List the names of the configured access control policies.' + }, + getPolicy: { + method: 'GET', + path: '/sys/policy/{{name}}', + description: 'Retrieve the rules for the named policy.' + }, + addPolicy: { + method: 'PUT', + path: '/sys/policy/{{name}}', + description: 'Add or update a policy.' + }, + removePolicy: { + method: 'DELETE', + path: '/sys/policy/{{name}}', + description: 'Delete the policy with the given name.' + }, + // auths + auths: { + method: 'GET', + path: '/sys/auth', + description: 'List the currently enabled credential backends: the name, the type of the backend, and a user friendly description of the purpose for the credential backend.' + }, + enableAuth: { + method: 'POST', + path: '/sys/auth/{{mount_point}}', + description: 'Enable a new auth backend.' + }, + disableAuth: { + method: 'DELETE', + path: '/sys/auth/{{mount_point}}', + description: 'Disable the auth backend at the given mount point.' + }, + // audits + audits: { + method: 'GET', + path: '/sys/audit', + description: 'List the currently enabled audit backends.' + }, + enableAudit: { + method: 'PUT', + path: '/sys/audit/{{name}}', + description: 'Enable an audit backend at the given path.' + }, + disableAudit: { + method: 'DELETE', + path: '/sys/audit/{{name}}', + description: 'Disable the given audit backend.' + }, + // secret handling + renew: { + method: 'PUT', + path: '/sys/leases/renew', + description: ` + +Renew a lease on a secret. + +### PARAMETERS + + increment (duration (sec)) + The desired increment in seconds to the lease. + + lease_id (string) + The lease identifier to renew. This is included with a lease. + + url_lease_id (string) + The lease identifier to renew. This is included with a lease. + +### DESCRIPTION + +When a secret is read, it may optionally include a lease interval +and a boolean indicating if renew is possible. For secrets that support +lease renewal, this endpoint is used to extend the validity of the +lease and to prevent an automatic revocation. + + `.trim(), + schema: { + req: { + type: 'object', + properties: { + lease_id: { + type: 'string' + }, + increment: { + type: 'integer' + } + }, + required: ['lease_id'] + }, + res: { + type: 'object', + properties: { + lease_id: { + type: 'string' + }, + renewable: { + type: 'boolean' + }, + lease_duration: { + type: 'integer' + } + } + } + } + }, + revoke: { + method: 'PUT', + path: '/sys/leases/revoke', + description: ` + +Revoke a leased secret immediately + +### PARAMETERS + + lease_id (string) + The lease identifier to renew. This is included with a lease. + + url_lease_id (string) + The lease identifier to renew. This is included with a lease. + +### DESCRIPTION + +When a secret is generated with a lease, it is automatically revoked +at the end of the lease period if not renewed. However, in some cases +you may want to force an immediate revocation. This endpoint can be +used to revoke the secret with the given Lease ID. + + `.trim(), + schema: { + req: { + type: 'object', + properties: { + lease_id: { + type: 'string' + } + }, + required: ['lease_id'] + } + } + }, + revokePrefix: { + method: 'PUT', + path: '/sys/revoke-prefix/{{path_prefix}}', + todo: 'find / create documentation' + }, + rotate: { + method: 'PUT', + path: '/sys/rotate', + description: ` + +Rotates the backend encryption key used to persist data. + + +### DESCRIPTION + +Rotate generates a new encryption key which is used to encrypt all +data going to the storage backend. The old encryption keys are kept so +that data encrypted using those keys can still be decrypted. + + `.trim() + }, + unwrap: { + method: 'POST', + path: '/sys/wrapping/unwrap', + description: ` + +Unwraps a response-wrapped token. + +### PARAMETERS + + token (string) + The unwrap token. + +### DESCRIPTION + +Unwraps a response-wrapped token. Unlike simply reading from cubbyhole/response, +this provides additional validation on the token, and rather than a JSON-escaped +string, the returned response is the exact same as the contained wrapped response. + + `.trim(), + schema: { + req: { + type: 'object', + properties: { + token: { + type: 'string' + } + } + } + } + }, + // token management + // - ancestors + tokenAccessors: { + method: 'LIST', + path: '/auth/token/accessors', + schema: TOKEN_ACCESSORS_AND_ROLES_SCHEME + }, + // - creation + tokenCreate: { + method: 'POST', + path: '/auth/token/create', + schema: TOKEN_CREATE_SCHEME + }, + tokenCreateOrphan: { + method: 'POST', + path: '/auth/token/create-orphan', + schema: TOKEN_CREATE_SCHEME + }, + tokenCreateRole: { + method: 'POST', + path: '/auth/token/create/{{role_name}}', + schema: TOKEN_CREATE_SCHEME + }, + // - lookup + tokenLookup: { + method: 'POST', + path: '/auth/token/lookup', + schema: { + req: { + type: 'object', + properties: { + token: { + type: 'string' + } + }, + required: ['token'] + }, + res: TOKEN_LOOKUP_RESPONSE_SCHEME + } + }, + tokenLookupAccessor: { + method: 'POST', + path: '/auth/token/lookup-accessor', + schema: { + req: { + type: 'object', + properties: { + accessor: { + type: 'string' + } + }, + required: ['accessor'] + }, + res: TOKEN_LOOKUP_RESPONSE_SCHEME + } + }, + tokenLookupSelf: { + method: 'GET', + path: '/auth/token/lookup-self', + schema: { res: TOKEN_LOOKUP_RESPONSE_SCHEME } + }, + // - renewal + tokenRenew: { + method: 'POST', + path: '/auth/token/renew', + schema: { + req: { + type: 'object', + properties: { + token: { + type: 'string' + }, + increment: { + type: ['integer', 'string'] + } + }, + required: ['token'] + }, + res: TOKEN_RESPONSE_SCHEME + } + }, + tokenRenewSelf: { + method: 'POST', + path: '/auth/token/renew-self', + schema: { + req: { + type: 'object', + properties: { + increment: { + type: ['integer', 'string'] + } + } + }, + res: TOKEN_RESPONSE_SCHEME + } + }, + // - revocation + tokenRevoke: { + method: 'POST', + path: '/auth/token/revoke', + schema: { + req: { + type: 'object', + properties: { + token: { + type: 'string' + } + }, + required: ['token'] + } + } + }, + tokenRevokeAccessor: { + method: 'POST', + path: '/auth/token/revoke-accessor', + schema: { + req: { + type: 'object', + properties: { + accessor: { + type: 'string' + } + }, + required: ['accessor'] + } + } + }, + tokenRevokeOrphan: { + method: 'POST', + path: '/auth/token/revoke-orphan', + schema: { + req: { + type: 'object', + properties: { + token: { + type: 'string' + } + }, + required: ['token'] + } + } + }, + tokenRevokeSelf: { + method: 'POST', + path: '/auth/token/revoke-self' + }, + // - roles + tokenRoles: { + method: 'GET', + path: '/auth/token/roles?list=true', + schema: TOKEN_ACCESSORS_AND_ROLES_SCHEME + }, + addTokenRole: { + method: 'POST', + path: '/auth/token/roles/{{role_name}}', + schema: { + req: { + type: 'object', + properties: { + allowed_policies: { + type: 'string' + }, + disallowed_policies: { + type: 'string' + }, + orphan: { + type: 'boolean' + }, + period: { + type: 'integer' + }, + renewable: { + type: 'boolean' + }, + path_suffix: { + type: 'string' + }, + explicit_max_ttl: { + type: 'integer' + } + } + } + } + }, + getTokenRole: { + method: 'GET', + path: '/auth/token/roles/{{role_name}}' + }, + removeTokenRole: { + method: 'DELETE', + path: '/auth/token/roles/{{role_name}}' + }, + approleRoles: { + method: 'LIST', + path: '/auth/{{mount_point=approle}}/role', + schema: { + res: APPROLE_RESPONSE_SCHEME + } + }, + // - approle + addApproleRole: { + method: 'POST', + path: '/auth/{{mount_point=approle}}/role/{{role_name}}', + schema: { + req: { + bind_secret_id: { + type: 'boolean' + }, + bound_cidr_list: { + type: 'string' + }, + policies: { + type: 'string' + }, + secret_id_num_uses: { + type: 'integer' + }, + secret_id_ttl: { + type: 'integer' + }, + token_num_uses: { + type: 'integer' + }, + token_ttl: { + type: 'integer' + }, + token_max_ttl: { + type: 'integer' + }, + period: { + type: 'integer' + } + } + } + }, + getApproleRole: { + method: 'GET', + path: '/auth/{{mount_point=approle}}/role/{{role_name}}', + schema: { + res: APPROLE_RESPONSE_SCHEME + } + }, + deleteApproleRole: { + method: 'DELETE', + path: '/auth/{{mount_point=approle}}/role/{{role_name}}' + }, + getApproleRoleId: { + method: 'GET', + path: '/auth/{{mount_point=approle}}/role/{{role_name}}/role-id', + schema: { + res: APPROLE_RESPONSE_SCHEME + } + }, + updateApproleRoleId: { + method: 'POST', + path: '/auth/{{mount_point=approle}}/role/{{role_name}}/role-id', + schema: { + req: { + type: 'object', + properties: { + role_id: { + type: 'string' + } + }, + required: ['role_id'] + } + } + }, + getApproleRoleSecret: { + method: 'POST', + path: '/auth/{{mount_point=approle}}' + + '/role/{{role_name}}/secret-id', + schema: { + req: { + type: 'object', + properties: { + metadata: { + type: 'string' + }, + cidr_list: { + type: 'array', + items: { + type: 'string' + } + } + } + }, + res: APPROLE_RESPONSE_SCHEME + } + }, + approleSecretAccessors: { + method: 'LIST', + path: '/auth/{{mount_point=approle}}' + + '/role/{{role_name}}/secret-id', + schema: { + res: APPROLE_RESPONSE_SCHEME + } + }, + approleSecretLookup: { + method: 'POST', + path: '/auth/{{mount_point=approle}}' + + '/role/{{role_name}}/secret-id/lookup', + schema: { + req: { + type: 'object', + properties: { + secret_id: { + type: 'string' + } + }, + required: ['secret_id'] + }, + res: APPROLE_RESPONSE_SCHEME + } + }, + approleSecretDestroy: { + method: 'POST', + path: '/auth/{{mount_point=approle}}' + + '/role/{{role_name}}/secret-id/destroy', + schema: { + req: { + type: 'object', + properties: { + secret_id: { + type: 'string' + } + }, + required: ['secret_id'] + } + } + }, + approleSecretAccessorLookup: { + method: 'POST', + path: '/auth/{{mount_point=approle}}' + + '/role/{{role_name}}/secret-id-accessor/lookup', + schema: { + req: { + type: 'object', + properties: { + secret_id: { + type: 'string' + } + }, + required: ['secret_id'] + } + } + }, + approleSecretAccessorDestroy: { + method: 'POST', + path: '/auth/{{mount_point=approle}}' + + '/role/{{role_name}}/secret-id-accessor/destroy' + }, + approleLogin: { + method: 'POST', + path: '/auth/{{mount_point=approle}}/login', + schema: { + req: { + type: 'object', + properties: { + role_id: { + type: 'string' + }, + secret_id: { + type: 'string' + } + }, + required: ['role_id', 'secret_id'] + }, + res: APPROLE_RESPONSE_SCHEME + } + }, + // utils + health: { + method: 'GET', + path: '/sys/health', + schema: { + query: { + type: 'object', + properties: { + standbyok: { + type: 'boolean' + }, + activecode: { + type: 'integer' + }, + standbycode: { + type: 'integer' + }, + sealedcode: { + type: 'integer' + }, + uninitcode: { + type: 'integer' + } + } + }, + res: { + type: 'object', + properties: { + cluster_id: { + type: 'string' + }, + cluster_name: { + type: 'string' + }, + version: { + type: 'string' + }, + server_time_utc: { + type: 'integer' + }, + standby: { + type: 'boolean' + }, + sealed: { + type: 'boolean' + }, + initialized: { + type: 'boolean' + } + } + } + } + }, + leader: { + method: 'GET', + path: '/sys/leader', + schema: { + res: { + type: 'object', + properties: { + ha_enabled: { + type: 'boolean' + }, + is_self: { + type: 'boolean' + }, + leader_address: { + type: 'string' + } + } + } + } + }, + stepDown: { + method: 'PUT', + path: '/sys/step-down' + } +} + +// adds a standard third party login feature +const addAuthLogin = (name) => (features[`${name}Login`] = { + method: 'POST', + path: `/auth/{{mount_point=${name}}}/login/{{username}}`, + schema: { + req: { + type: 'object', + properties: { + password: { + type: 'string' + } + }, + required: ['password'] + }, + res: TOKEN_RESPONSE_SCHEME + } +}) + +// add all third party logins +const authLogins = [ + 'github', + 'userpass', + 'ldap', + 'okta', + 'radius'] +authLogins.forEach(addAuthLogin) + +console.log(features.githubLogin) + +module.exports = features diff --git a/src/interface/resource-methods.js b/src/interface/resource-methods.js new file mode 100644 index 0000000..15cda70 --- /dev/null +++ b/src/interface/resource-methods.js @@ -0,0 +1,82 @@ +module.exports = [{ + // vault help + name: 'help', + query: '?help=1', + operation: 'GET', + description: ` + +Look up the help for a path. + +All endpoints in Vault from system paths, secret paths, and credential +providers provide built-in help. This command looks up and outputs that +help. + +The command requires that the vault be unsealed, because otherwise +the mount points of the backends are unknown. + + `.trim() + +// vault data operations +}, { + // - read + name: 'read', + operation: 'GET', + description: ` + +Read data from Vault. + +Reads data at the given path from Vault. This can be used to read +secrets and configuration as well as generate dynamic values from +materialized backends. Please reference the documentation for the +backends in use to determine key structure. + + `.trim() +}, { + // - write + name: 'write', + operation: 'PUT', + description: ` + +Write data (secrets or configuration) into Vault. + +Write sends data into Vault at the given path. The behavior of the write is +determined by the backend at the given path. For example, writing to +"aws/policy/ops" will create an "ops" IAM policy for the AWS backend +(configuration), but writing to "consul/foo" will write a value directly into +Consul at that key. Check the documentation of the logical backend you're +using for more information on key structure. + +Data is sent via additional arguments in "key=value" pairs. If value begins +with an "@", then it is loaded from a file. Write expects data in the file to +be in JSON format. If you want to start the value with a literal "@", then +prefix the "@" with a slash: "\\@". + + `.trim() +}, { + // - list + name: 'list', + operation: 'LIST', + description: ` + +List data from Vault. + +Retrieve a listing of available data. The data returned, if any, is backend- +and endpoint-specific. + + `.trim() +}, { + // - delete + name: 'delete', + operation: 'DELETE', + description: ` + +Delete data (secrets or configuration) from Vault. + +Delete sends a delete operation request to the given path. The +behavior of the delete is determined by the backend at the given +path. For example, deleting "aws/policy/ops" will delete the "ops" +policy for the AWS backend. Use "vault help" for more details on +whether delete is supported for a path and what the behavior is. + + `.trim() +}] diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..c568397 --- /dev/null +++ b/src/main.js @@ -0,0 +1,308 @@ +const debug = require('debug')('node-vault') +// tv4 is a tool to validate json structures +const tv4 = require('tv4') +const request = require('request-promise-native') + +// ---------------- +// import features and methods definitions + +const FEATURES = require('./interface/features') +const RESOURCE_METHODS = require('./interface/resource-methods') + +// ---------------- +// request validation schema + +const REQUEST_SCHEMA = { + type: 'object', + properties: { + path: { + type: 'string' + }, + method: { + type: 'string' + } + }, + required: ['path', 'method'] +} + +/** + * Vault client class (not exported by the module, see + * explanation at the end of this file - src/main.js) + * + * @param {object} [options={}] Options for the vault client + * @param {string} [options.apiVersion='v1'] Vault's API version + * @param {string} [options.endpoint='http://127.0.0.1:8200'] Vault endpoint address + * @param {token} [options.token=''] Vault authentication token + * @param {object} [options.features=''] JSON definition of the features + * @param {object} [options.resourceMethods=''] JSON definition of the resource methods + * @param {object} [options.requestOptions={}] Request options + * @param {object} [options._test={}] Testing options (only for unit testing, DON'T USE IT IN PRODUCTION!) + */ +class VaultClient { + constructor (options = {}) { + // optionally overwrite features + // TODO: maybe a better behavior is to only extend the + // default features and resource methods instead of + // replacing them entirely, and move this overwriting + // option to the _test namespace if needed + this._features = options.features || FEATURES + this._resourceMethods = options.resourceMethods || RESOURCE_METHODS + + // save client options + this._options = { + apiVersion: options.apiVersion || 'v1', + endpoint: options.endpoint || process.env.VAULT_ADDR || 'http://127.0.0.1:8200', + token: options.token || process.env.VAULT_TOKEN, + requestOptions: {}, + insecure: (options._test && options._test.insecure) || false + } + + // request testing stub injection + this.request = ((options._test && options._test['request-promise']) || request).defaults({ + json: true, + resolveWithFullResponse: true, + simple: false, + strictSSL: !process.env.VAULT_SKIP_VERIFY + }) + + // create client and save it + this.client = this._createClient() + } + + // ---------------- + // data + + _getOption (option) { + return this._options[option] + } + + _validate (json, schema) { + // ignore validation if no schema + if (!schema) return + const valid = tv4.validate(json, schema) + if (!valid) { + debug(tv4.error.dataPath) + debug(tv4.error.message) + throw tv4.error + } + } + + // ---------------- + // method generators + + _generateFeature (data) { + return (args = {}) => { + // merge all request options + const requestOptions = Object.assign({}, + this._getOption('requestOptions'), + args.requestOptions) + + // generate request options + requestOptions.method = data.method + requestOptions.path = data.path + delete args.requestOptions + requestOptions.json = args + + // no schema object -> no validation + if (!data.schema) return this._request(requestOptions) + // else do validation of request URL and body + try { + this._validate(requestOptions.json, data.schema.req) + this._validate(requestOptions.json, data.schema.query) + } catch (error) { + return Promise.reject(error) + } + + // extend the options and execute request + const extendedOptions = this._extendRequestOptions(data, requestOptions) + return this._request(extendedOptions) + } + } + + _generateResourceMethod (operation, query = '') { + return (...args) => { + // by using ...args we get an array of arguments + // similar to the arguments object in non-arrow functions + + // the arguments for a resource method are: + // client.(path, [data], requestOptions) + + // the data argument is not exactly optional, it will not exist + // for all methods except the ones using 'PUT', where it will + // have a fixed second spot (and requestOptions becomes third) + const path = args[0] + + // merge all request options + const requestOptions = Object.assign({}, + this._getOption('requestOptions'), + operation === 'PUT' ? args[2] : args[1]) + + // generate request options + requestOptions.path = `/${path}${query}` + requestOptions.method = operation + if (operation === 'PUT') requestOptions.json = args[1] + + // execute request + return this._request(requestOptions) + } + } + + // ---------------- + // requests + + _extendRequestOptions (original, options) { + const schema = original.schema.query + // no schema for the query -> no need to extend + if (!schema) return options + // create params array + const params = [] + // loop ONLY through schema params + for (const key of Object.keys(schema.properties)) { + // if and only if the property exists in the new + // params, add it to the extended params array + key in options.json && + params.push(`${key}=${encodeURIComponent(options.json[key])}`) + } + // this way, only whitelisted params (on the schema) + // will be allowed in the request + + // add params (if any) to path as URL query + if (params.length) options.path += `?${params.join('&')}` + return options + } + + _formatRequest (uriTemplate, values = {}) { + return uriTemplate.replace(/{{([\S]+?)}}/g, (a, b, c) => { + const parts = b.split('=') + const prop = parts[0] + const defaultValue = parts[1] || '' + return values[prop] || defaultValue + }) + } + + _request (options = {}) { + // validate + if (!tv4.validate(options, REQUEST_SCHEMA)) return Promise.reject(tv4.error) + // create URI template + const uriTemplate = `${this._getOption('endpoint')}/${this._getOption('apiVersion')}${options.path}` + // replace variables in uri + const uri = this._formatRequest(uriTemplate, options.json) + // replace unicode encodings + .replace(///g, '/') + // add URI + options.uri = uri + // add headers + options.headers = options.headers || {} + // add token + const token = this._getOption('token') + typeof token === 'string' && token.length && + (options.headers['X-Vault-Token'] = token) + + // execute request + debug(options.method, uri) + return this.request(options) + // handle response from vault + .then(response => this._handleVaultResponse(response)) + } + + _handleVaultResponse (response) { + // throw exception is there's no response argument + if (!response) return Promise.reject(new Error('[node-vault:handleVaultResponse] No response parameter')) + + // if response status code is not 200 or 204 (ok responses) + debug(response.statusCode) + if (response.statusCode !== 200 && response.statusCode !== 204) { + // healthcheck response is never handled as an error + if (response.request.path.match(/sys\/health/) !== null) return Promise.resolve(response.body) + + // get the error message + let message + if (response.body && response.body.errors && response.body.errors.length) { + message = response.body.errors[0] + } else { + message = `Status ${response.statusCode}` + } + + // throw an exception with the message + return Promise.reject(new Error(message)) + } + + // else return the response body + return Promise.resolve(response.body) + } + + // ---------------- + // authentication + + _setToken (token) { + if (typeof token === 'string' && token.length) this._options.token = token + else throw new Error('[node-vault:_setToken] Incorrect token parameter') + } + + _removeToken () { + this.token = null + } + + // ---------------- + // client creation + + _createClient () { + const client = {} + + // add a feature to the current client object + const addFeature = name => + (client[name] = (...args) => { + const logMessages = [`${name}()`] + args.length && logMessages.push('- arguments:', args) + debug(...logMessages) + return this._generateFeature(this._features[name])(...args) + }) + + // add a resource method to the current client object + const addResourceMethod = (method) => + (client[method.name] = (...args) => { + const logMessages = [`${method.name}()`] + args.length && logMessages.push('- arguments:', args) + debug(...logMessages) + return this._generateResourceMethod(method.operation, method.query)(...args) + }) + + // add all resource methods + this._resourceMethods.forEach(addResourceMethod) + + // add all features + Object.keys(this._features).forEach(addFeature) + + // add login and logout (setToken and removeToken aliases) + client.login = token => this._setToken(token) + client.logout = () => this._removeToken() + + // add insecure properties and methods to client + // if the insecure option is switched on (for testing) + if (this._options.insecure) { + client.endpoint = this._options.endpoint + client.apiVersion = this._options.apiVersion + client.handleVaultResponse = + (...args) => this._handleVaultResponse(...args) + client.generateFeature = + (...args) => this._generateFeature(...args) + client.request = + (...args) => this._request(...args) + client.formatRequest = + (...args) => this._formatRequest(...args) + } + + // return the generated client + return client + } +} + +// for security and compatibility, instead of the class, +// a function that encapsulates the client will be exported, +// blocking access to any of the instance methods or properties + +// this also means that the interface will be defined +// exclusively and explicitly in the src/features.js and +// src/resource-methods.js files + +module.exports = options => new VaultClient(options).client diff --git a/test/integration.js b/test/integration.js index ce34c65..2a9b85b 100644 --- a/test/integration.js +++ b/test/integration.js @@ -1,44 +1,47 @@ -const chai = require('chai'); -const dirtyChai = require('dirty-chai'); -const should = chai.Should; +/* eslint-env mocha */ +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const should = chai.Should -should(); -chai.use(dirtyChai); +should() +chai.use(dirtyChai) -const vault = require('./../src/index.js')(); -// use json schema in commands.js validate response -const commands = require('./../src/commands.js'); -const tv4 = require('tv4'); -const assert = require('assert'); +const vault = require('./../src/main')() +// import features to validate responses against their json schemas +const features = require('./../src/interface/features') +// tv4 is a tool to validate json structures +const tv4 = require('tv4') +const assert = require('assert') -const validResult = (commandName, result) => { - const schema = commands[commandName].schema.res; - return tv4.validate(result, schema); -}; +// validates a response by feature name +const validateResponse = (featureName, response) => { + const schema = features[featureName].schema.res + return tv4.validate(response, schema) +} describe('integration', () => { describe('node-vault', () => { it('should initialize a vault server', (done) => { vault.init({ secret_shares: 1, secret_threshold: 1 }) - .then((result) => { - vault.token = result.root_token; - assert(validResult('init', result)); - return done(); - }) - .catch((err) => { - if (err.message === 'Vault is already initialized') { - return done(); - } - return done(err); - }); - }); + .then((result) => { + vault.token = result.root_token + assert(validateResponse('init', result)) + return done() + }) + .catch((err) => { + if (err.message === 'Vault is already initialized') { + return done() + } + return done(err) + }) + }) it('should show the current status of the vault server', (done) => { vault.status() - .then((result) => { - assert(validResult('status', result)); - return done(); - }) - .catch(done); - }); - }); -}); + .then((result) => { + assert(validateResponse('status', result)) + return done() + }) + .catch(done) + }) + }) +}) diff --git a/test/mocha.opts b/test/mocha.opts index aa47994..7f61ad8 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,5 +1,4 @@ --reporter spec --ui bdd --colors ---growl --timeout 2000 diff --git a/test/unit.js b/test/unit.js index 09466cf..2d539f2 100644 --- a/test/unit.js +++ b/test/unit.js @@ -1,284 +1,290 @@ -const sinon = require('sinon'); -const sinonChai = require('sinon-chai'); -const chai = require('chai'); -const dirtyChai = require('dirty-chai'); -const should = chai.Should; +/* eslint-env mocha */ +const sinon = require('sinon') +const sinonChai = require('sinon-chai') +const chai = require('chai') +const dirtyChai = require('dirty-chai') -should(); -chai.use(dirtyChai); -chai.use(sinonChai); +const nodeVault = require('./../src/main') -const index = require('./../src/index.js'); +const should = chai.Should -const error = new Error('should not be called'); +should() +chai.use(dirtyChai) +chai.use(sinonChai) + +const error = new Error('should not be called') describe('node-vault', () => { describe('module', () => { after(() => { - process.env.VAULT_SKIP_VERIFY = ''; - }); + process.env.VAULT_SKIP_VERIFY = '' + }) it('should export a function that returns a new client', () => { - const v = index(); - index.should.be.a('function'); - v.should.be.an('object'); - }); + const v = nodeVault() + nodeVault.should.be.a('function') + v.should.be.an('object') + }) it('should set default values for request library', () => { - const defaultsStub = sinon.stub(); + const defaultsStub = sinon.stub() - index({ - 'request-promise': { - defaults: defaultsStub, - }, - }); + nodeVault({ + _test: { + 'request-promise': { + defaults: defaultsStub + } + } + }) - defaultsStub.should.be.calledOnce(); + defaultsStub.should.be.calledOnce() defaultsStub.should.be.calledWithExactly({ json: true, simple: false, resolveWithFullResponse: true, - strictSSL: true, - }); - }); + strictSSL: true + }) + }) it('should disable ssl security based on vault environment variable', () => { - const defaultsStub = sinon.stub(); + const defaultsStub = sinon.stub() // see https://www.vaultproject.io/docs/commands/environment.html for details - process.env.VAULT_SKIP_VERIFY = 'catpants'; + process.env.VAULT_SKIP_VERIFY = 'catpants' - index({ - 'request-promise': { - defaults: defaultsStub, - }, - }); + nodeVault({ + _test: { + 'request-promise': { + defaults: defaultsStub + } + } + }) - defaultsStub.should.be.calledOnce(); + defaultsStub.should.be.calledOnce() defaultsStub.should.be.calledWithExactly({ json: true, simple: false, resolveWithFullResponse: true, - strictSSL: false, - }); - }); - }); - + strictSSL: false + }) + }) + }) describe('client', () => { - let request = null; - let response = null; - let vault = null; + let request = null + let response = null + let vault = null // helper - function getURI(path) { - return [vault.endpoint, vault.apiVersion, path].join('/'); + function getURI (path) { + return [vault.endpoint, vault.apiVersion, path].join('/') } - function assertRequest(thisRequest, params, done) { + function assertRequest (thisRequest, params, done) { return () => { - thisRequest.should.have.calledOnce(); - thisRequest.calledWithMatch(params).should.be.ok(); - return done(); - }; + thisRequest.should.have.calledOnce() + thisRequest.calledWithMatch(params).should.be.ok() + return done() + } } beforeEach(() => { // stub requests - request = sinon.stub(); - response = sinon.stub(); - response.statusCode = 200; + request = sinon.stub() + response = sinon.stub() + response.statusCode = 200 request.returns({ - then(fn) { - return fn(response); - }, - catch(fn) { - return fn(); + then (fn) { + return fn(response) }, - }); + catch (fn) { + return fn() + } + }) - vault = index( - { - endpoint: 'http://localhost:8200', - token: '123', + vault = nodeVault({ + endpoint: 'http://localhost:8200', + token: '123', + _test: { + insecure: true, 'request-promise': { - defaults: () => request, // dependency injection of stub - }, + defaults: () => request // dependency injection of stub + } } - ); - }); + }) + }) describe('help(path, options)', () => { it('should response help text for any path', done => { - const path = 'sys/policy'; + const path = 'sys/policy' const params = { method: 'GET', - uri: `${getURI(path)}?help=1`, - }; + uri: `${getURI(path)}?help=1` + } vault.help(path) - .then(assertRequest(request, params, done)) - .catch(done); - }); + .then(assertRequest(request, params, done)) + .catch(done) + }) it('should handle undefined options', done => { - const path = 'sys/policy'; + const path = 'sys/policy' const params = { method: 'GET', - uri: `${getURI(path)}?help=1`, - }; + uri: `${getURI(path)}?help=1` + } vault.help(path) .then(assertRequest(request, params, done)) - .catch(done); - }); - }); + .catch(done) + }) + }) describe('list(path, requestOptions)', () => { it('should list entries at the specific path', done => { - const path = 'secret/hello'; + const path = 'secret/hello' const params = { method: 'LIST', - uri: getURI(path), - }; + uri: getURI(path) + } vault.list(path) .then(assertRequest(request, params, done)) - .catch(done); - }); - }); + .catch(done) + }) + }) describe('write(path, data, options)', () => { it('should write data to path', done => { - const path = 'secret/hello'; + const path = 'secret/hello' const data = { - value: 'world', - }; + value: 'world' + } const params = { method: 'PUT', - uri: getURI(path), - }; + uri: getURI(path) + } vault.write(path, data) .then(assertRequest(request, params, done)) - .catch(done); - }); + .catch(done) + }) it('should handle undefined options', done => { - const path = 'secret/hello'; + const path = 'secret/hello' const data = { - value: 'world', - }; + value: 'world' + } const params = { method: 'PUT', - uri: getURI(path), - }; + uri: getURI(path) + } vault.write(path, data) .then(assertRequest(request, params, done)) - .catch(done); - }); - }); + .catch(done) + }) + }) describe('read(path, options)', () => { it('should read data from path', done => { - const path = 'secret/hello'; + const path = 'secret/hello' const params = { method: 'GET', - uri: getURI(path), - }; + uri: getURI(path) + } vault.read(path) .then(assertRequest(request, params, done)) - .catch(done); - }); + .catch(done) + }) it('should handle undefined options', done => { - const path = 'secret/hello'; + const path = 'secret/hello' const params = { method: 'GET', - uri: getURI(path), - }; + uri: getURI(path) + } vault.read(path) .then(assertRequest(request, params, done)) - .catch(done); - }); - }); + .catch(done) + }) + }) describe('delete(path, options)', () => { it('should delete data from path', done => { - const path = 'secret/hello'; + const path = 'secret/hello' const params = { method: 'DELETE', - uri: getURI(path), - }; + uri: getURI(path) + } vault.delete(path) .then(assertRequest(request, params, done)) - .catch(done); - }); + .catch(done) + }) it('should handle undefined options', done => { - const path = 'secret/hello'; + const path = 'secret/hello' const params = { method: 'DELETE', - uri: getURI(path), - }; + uri: getURI(path) + } vault.delete(path) .then(assertRequest(request, params, done)) - .catch(done); - }); - }); + .catch(done) + }) + }) describe('unwrap(options)', () => { it('should return original response', done => { - const path = 'sys/wrapping/unwrap'; + const path = 'sys/wrapping/unwrap' const params = { method: 'POST', - uri: getURI(path), - }; + uri: getURI(path) + } vault.unwrap({ token: 'token' }) .then(assertRequest(request, params, done)) - .catch(done); - }); - }); + .catch(done) + }) + }) describe('handleVaultResponse(response)', () => { it('should return a function that handles errors from vault server', () => { - const fn = vault.handleVaultResponse; - fn.should.be.a('function'); - }); + const fn = vault.handleVaultResponse + fn.should.be.a('function') + }) it('should return a Promise with the body if successful', done => { - const data = { hello: 1 }; - response.body = data; - const promise = vault.handleVaultResponse(response); + const data = { hello: 1 } + response.body = data + const promise = vault.handleVaultResponse(response) promise.then(body => { - body.should.equal(data); - return done(); - }); - }); + body.should.equal(data) + return done() + }) + }) it('should return a Promise with the error if failed', done => { - response.statusCode = 500; + response.statusCode = 500 response.body = { - errors: ['Something went wrong.'], - }; + errors: ['Something went wrong.'] + } response.request = { - path: 'test', - }; - const promise = vault.handleVaultResponse(response); + path: 'test' + } + const promise = vault.handleVaultResponse(response) promise.catch(err => { - err.message.should.equal(response.body.errors[0]); - return done(); - }); - }); + err.message.should.equal(response.body.errors[0]) + return done() + }) + }) it('should return the status code if no error in the response', done => { - response.statusCode = 500; + response.statusCode = 500 response.request = { - path: 'test', - }; - const promise = vault.handleVaultResponse(response); + path: 'test' + } + const promise = vault.handleVaultResponse(response) promise.catch(err => { - err.message.should.equal(`Status ${response.statusCode}`); - return done(); - }); - }); + err.message.should.equal(`Status ${response.statusCode}`) + return done() + }) + }) it('should not handle response from health route as error', done => { const data = { @@ -286,50 +292,50 @@ describe('node-vault', () => { sealed: true, standby: true, server_time_utc: 1474301338, - version: 'Vault v0.6.1', - }; - response.statusCode = 503; - response.body = data; + version: 'Vault v0.6.1' + } + response.statusCode = 503 + response.body = data response.request = { - path: '/v1/sys/health', - }; - const promise = vault.handleVaultResponse(response); + path: '/v1/sys/health' + } + const promise = vault.handleVaultResponse(response) promise.then(body => { - body.should.equal(data); - return done(); - }); - }); + body.should.equal(data) + return done() + }) + }) it('should return error if error on request path with health and not sys/health', done => { - response.statusCode = 404; + response.statusCode = 404 response.body = { - errors: [], - }; + errors: [] + } response.request = { - path: '/v1/sys/policies/applications/im-not-sys-health/app', - }; + path: '/v1/sys/policies/applications/im-not-sys-health/app' + } vault.handleVaultResponse(response) .then(() => done(error)) .catch(err => { - err.message.should.equal(`Status ${response.statusCode}`); - return done(); - }); - }); + err.message.should.equal(`Status ${response.statusCode}`) + return done() + }) + }) it('should return a Promise with the error if no response is passed', done => { - const promise = vault.handleVaultResponse(); + const promise = vault.handleVaultResponse() promise.catch((err) => { - err.message.should.equal('No response passed'); - return done(); - }); - }); - }); + err.message.should.equal('[node-vault:handleVaultResponse] No response parameter') + return done() + }) + }) + }) - describe('generateFunction(name, config)', () => { + describe('generateFeature(name, config)', () => { const config = { method: 'GET', - path: '/myroute', - }; + path: '/myroute' + } const configWithSchema = { method: 'GET', @@ -340,13 +346,13 @@ describe('node-vault', () => { properties: { testProperty: { type: 'integer', - minimum: 1, - }, + minimum: 1 + } }, - required: ['testProperty'], - }, - }, - }; + required: ['testProperty'] + } + } + } const configWithQuerySchema = { method: 'GET', @@ -357,101 +363,143 @@ describe('node-vault', () => { properties: { testParam1: { type: 'integer', - minimum: 1, + minimum: 1 }, testParam2: { - type: 'string', - }, + type: 'string' + } }, - required: ['testParam1', 'testParam2'], - }, - }, - }; + required: ['testParam1', 'testParam2'] + } + } + } + + /* TODO: create equivalent test by replacing features + with some custom ones and checking their existence it('should generate a function with name as defined in config', () => { - const name = 'myGeneratedFunction'; - vault.generateFunction(name, config); - vault.should.have.property(name); - const fn = vault[name]; - fn.should.be.a('function'); - }); + const name = 'myGeneratedFunction' + vault.generateFeature(name, config) + vault.should.have.property(name) + const fn = vault[name] + fn.should.be.a('function') + }) + */ describe('generated function', () => { it('should return a promise', done => { - const name = 'myGeneratedFunction'; - vault.generateFunction(name, config); - const fn = vault[name]; - const promise = fn(); - request.calledOnce.should.be.ok(); - /* eslint no-unused-expressions: 0*/ - promise.should.be.promise; - promise.then(done) - .catch(done); - }); + const feature = vault.generateFeature(config) + const promise = feature() + request.calledOnce.should.be.ok() + /* eslint no-unused-expressions: 0 */ + promise.should.be.promise + promise + .then(done) + .catch(done) + }) it('should handle config with schema property', done => { - const name = 'myGeneratedFunction'; - vault.generateFunction(name, configWithSchema); - const fn = vault[name]; - const promise = fn({ testProperty: 3 }); - promise.then(done).catch(done); - }); + const feature = vault.generateFeature(configWithSchema) + feature({ testProperty: 3 }) + .then(done) + .catch(done) + }) it('should handle invalid arguments via schema property', done => { - const name = 'myGeneratedFunction'; - vault.generateFunction(name, configWithSchema); - const fn = vault[name]; - const promise = fn({ testProperty: 'wrong data type here' }); - promise.catch(err => { - err.message.should.equal('Invalid type: string (expected integer)'); - return done(); - }); - }); + const feature = vault.generateFeature(configWithSchema) + feature({ testProperty: 'wrong data type here' }) + .catch(err => { + err.message.should.equal('Invalid type: string (expected integer)') + return done() + }) + }) it('should handle schema with query property', done => { - const name = 'myGeneratedFunction'; - vault.generateFunction(name, configWithQuerySchema); - const fn = vault[name]; - const promise = fn({ testParam1: 3, testParam2: 'hello' }); + const feature = vault.generateFeature(configWithQuerySchema) + const promise = feature({ testParam1: 3, testParam2: 'hello' }) const options = { - path: '/myroute?testParam1=3&testParam2=hello', - }; + path: '/myroute?testParam1=3&testParam2=hello' + } promise .then(() => { - request.calledWithMatch(options).should.be.ok(); - done(); + request.calledWithMatch(options).should.be.ok() + done() }) - .catch(done); - }); - }); - }); + .catch(done) + }) + }) + }) + + describe('_formatRequest (uriTemplate, values)', () => { + it('should insert the parameters in the URI template', done => { + const path = '/test/{{param_1}}/test/{{param_2}}' + const values = { + param_1: 'test_value_1', + param_2: 'test_value_2' + } + const result = vault.formatRequest(path, values) + result.should.equal('/test/test_value_1/test/test_value_2') + return done() + }) + + it('should insert a default value if missing', done => { + const path = '/test/{{param_1}}/test/{{param_2=default_value_2}}' + const values = { + param_1: 'test_value_1' + } + const result = vault.formatRequest(path, values) + result.should.equal('/test/test_value_1/test/default_value_2') + return done() + }) + + it('should not insert a default value if not missing', done => { + const path = '/test/{{param_1}}/test/{{param_2=default_value_2}}' + const values = { + param_1: 'test_value_1', + param_2: 'test_value_2' + } + const result = vault.formatRequest(path, values) + result.should.equal('/test/test_value_1/test/test_value_2') + return done() + }) + + it('should not fail if value is missing without a default', done => { + const path = '/test/{{param_1}}/test/{{param_2}}' + const values = { + param_1: 'test_value_1' + } + const result = vault.formatRequest(path, values) + result.should.equal('/test/test_value_1/test/') + return done() + }) + }) describe('request(options)', () => { it('should reject if options are undefined', done => { vault.request() - .then(() => done(error)) - .catch(() => done()); - }); + .then(() => done(error)) + .catch(() => done()) + }) it('should handle undefined path in options', done => { const promise = vault.request({ - method: 'GET', - }); + method: 'GET' + }) promise.catch(err => { - err.message.should.equal('Missing required property: path'); - return done(); - }); - }); + err.message.should.equal('Missing required property: path') + return done() + }) + }) it('should handle undefined method in options', done => { const promise = vault.request({ - path: '/', - }); + path: '/' + }) promise.catch(err => { - err.message.should.equal('Missing required property: method'); - return done(); - }); - }); - }); - }); -}); + err.message.should.equal('Missing required property: method') + return done() + }) + }) + }) + }) +}) diff --git a/yarn.lock b/yarn.lock index dc559d8..b3cc1f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,58 +2,49 @@ # yarn lockfile v1 -abbrev@1: - version "1.1.1" - resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - -abbrev@1.0.x: - version "1.0.9" - resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - acorn-jsx@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" dependencies: acorn "^3.0.4" acorn@^3.0.4: version "3.3.0" - resolved "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^5.1.1: - version "5.1.2" - resolved "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7" +acorn@^5.2.1: + version "5.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822" -agent-base@2: - version "2.1.1" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7" +agent-base@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.1.2.tgz#80fa6cde440f4dcf9af2617cf246099b5d99f0c8" dependencies: - extend "~3.0.0" - semver "~5.0.1" + es6-promisify "^5.0.0" ajv-keywords@^1.0.0: version "1.5.1" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" ajv@^4.7.0: version "4.11.8" - resolved "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" ajv@^5.1.0: - version "5.2.3" - resolved "https://registry.npmjs.org/ajv/-/ajv-5.2.3.tgz#c06f598778c44c6b161abafe3466b81ad1814ed2" + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" - json-stable-stringify "^1.0.1" align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" - resolved "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" dependencies: kind-of "^3.0.2" longest "^1.0.1" @@ -61,147 +52,280 @@ align-text@^0.1.1, align-text@^0.1.3: amdefine@>=0.0.4: version "1.0.1" - resolved "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" ansi-escapes@^1.1.0: version "1.4.0" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + +ansi-escapes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" ansi-regex@^2.0.0: version "2.1.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" ansi-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" ansi-styles@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + +append-transform@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" + dependencies: + default-require-extensions "^1.0.0" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" argparse@^1.0.7: version "1.0.9" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" dependencies: sprintf-js "~1.0.2" +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + array-union@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" dependencies: array-uniq "^1.0.1" array-uniq@^1.0.1: version "1.0.3" - resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +array.prototype.find@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.0.4.tgz#556a5c5362c08648323ddaeb9de9d14bc1864c90" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" -arrify@^1.0.0: +arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" asn1@~0.2.3: version "0.2.3" - resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" assertion-error@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" -async@1.x, async@^1.4.0: +async@^1.4.0: version "1.5.2" - resolved "https://registry.npmjs.org/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" aws-sign2@~0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" aws4@^1.6.0: version "1.6.0" - resolved "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + +babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-generator@^6.18.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.6" + trim-right "^1.0.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.16.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.18.0, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.18.0, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" balanced-match@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" bcrypt-pbkdf@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" dependencies: tweetnacl "^0.14.3" -boom@2.x.x: - version "2.10.1" - resolved "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - boom@4.x.x: version "4.3.1" - resolved "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" + resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" dependencies: hoek "4.x.x" boom@5.x.x: version "5.2.0" - resolved "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" + resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" dependencies: hoek "4.x.x" brace-expansion@^1.1.7: version "1.1.8" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" -builtin-modules@^1.1.1: +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + +builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +caching-transform@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" + dependencies: + md5-hex "^1.2.0" + mkdirp "^0.5.1" + write-file-atomic "^1.1.4" caller-path@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" dependencies: callsites "^0.2.0" callsites@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" camelcase@^1.0.2: version "1.2.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" caseless@~0.12.0: version "0.12.0" - resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" center-align@^0.1.1: version "0.1.3" - resolved "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" dependencies: align-text "^0.1.3" lazy-cache "^1.0.3" -chai@^3.5.0: - version "3.5.0" - resolved "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" +chai@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" dependencies: assertion-error "^1.0.1" - deep-eql "^0.1.3" - type-detect "^1.0.0" + check-error "^1.0.1" + deep-eql "^3.0.0" + get-func-name "^2.0.0" + pathval "^1.0.0" + type-detect "^4.0.0" chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -209,79 +333,122 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -ci-info@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.1.tgz#47b44df118c48d2597b56d342e7e25791060171a" +chalk@^2.0.0, chalk@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + +check-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" circular-json@^0.3.1: version "0.3.3" - resolved "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" cli-cursor@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" dependencies: restore-cursor "^1.0.1" -cli-table@^0.3.1: - version "0.3.1" - resolved "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-table2@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/cli-table2/-/cli-table2-0.2.0.tgz#2d1ef7f218a0e786e214540562d4bd177fe32d97" dependencies: - colors "1.0.3" + lodash "^3.10.1" + string-width "^1.0.1" + optionalDependencies: + colors "^1.1.2" cli-width@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - -cliclopts@^1.1.0: - version "1.1.1" - resolved "https://registry.npmjs.org/cliclopts/-/cliclopts-1.1.1.tgz#69431c7cb5af723774b0d3911b4c37512431910f" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" cliui@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" dependencies: center-align "^0.1.1" right-align "^0.1.1" wordwrap "0.0.2" +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc" + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + co@^4.6.0: version "4.6.0" - resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" code-point-at@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" -colors@1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +colors@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" dependencies: delayed-stream "~1.0.0" -commander@0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" - -commander@2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" "commander@>= 0.5.2": - version "2.11.0" - resolved "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + version "2.12.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.4.6: +concat-stream@^1.5.2: version "1.6.0" - resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" dependencies: inherits "^2.0.3" readable-stream "^2.2.2" @@ -289,73 +456,114 @@ concat-stream@^1.4.6: contains-path@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + +convert-source-map@^1.3.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +core-js@^2.4.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cross-spawn@^4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" cryptiles@3.x.x: version "3.1.2" - resolved "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" dependencies: boom "5.x.x" -cvss@^1.0.0: +cvss@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/cvss/-/cvss-1.0.2.tgz#df67e92bf12a796f49e928799c8db3ba74b9fcd6" + resolved "https://registry.yarnpkg.com/cvss/-/cvss-1.0.2.tgz#df67e92bf12a796f49e928799c8db3ba74b9fcd6" d@1: version "1.0.0" - resolved "https://registry.npmjs.org/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" dependencies: es5-ext "^0.10.9" dashdash@^1.12.0: version "1.14.1" - resolved "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" dependencies: assert-plus "^1.0.0" -debug@2, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0: - version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - dependencies: - ms "2.0.0" +debug-log@^1.0.0, debug-log@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" -debug@2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" +debug@3.1.0, debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: - ms "0.7.1" + ms "2.0.0" -debug@3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" +debug@^2.1.1, debug@^2.2.0, debug@^2.6.8: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -decamelize@^1.0.0: +decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" -deep-eql@^0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" +deep-eql@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" dependencies: - type-detect "0.1.1" - -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" + type-detect "^4.0.0" deep-is@~0.1.3: version "0.1.3" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +default-require-extensions@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" + dependencies: + strip-bom "^2.0.0" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +deglob@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/deglob/-/deglob-2.1.0.tgz#4d44abe16ef32c779b4972bd141a80325029a14a" + dependencies: + find-root "^1.0.0" + glob "^7.0.5" + ignore "^3.0.9" + pkg-config "^1.1.0" + run-parallel "^1.1.2" + uniq "^1.0.1" del@^2.0.2: version "2.2.2" - resolved "https://registry.npmjs.org/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" dependencies: globby "^5.0.0" is-path-cwd "^1.0.0" @@ -367,19 +575,29 @@ del@^2.0.2: delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" -diff@1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" -dirty-chai@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/dirty-chai/-/dirty-chai-1.2.2.tgz#78495e619635f7fe44219aa4c837849bf183142e" +diff@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" -docco@^0.7.0: - version "0.7.0" - resolved "https://registry.npmjs.org/docco/-/docco-0.7.0.tgz#d606e5a990cba052ca1e1803a9c587ecee3c5c38" +diff@^3.1.0: + version "3.4.0" + resolved "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" + +dirty-chai@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/dirty-chai/-/dirty-chai-2.0.1.tgz#6b2162ef17f7943589da840abc96e75bda01aff3" + +docco@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/docco/-/docco-0.8.0.tgz#ec71470fe52808f4dbba4fab71380dcdfe9f5396" dependencies: commander ">= 0.5.2" fs-extra ">= 0.6.0" @@ -387,44 +605,67 @@ docco@^0.7.0: marked ">= 0.2.7" underscore ">= 1.0.0" -doctrine@1.3.x: - version "1.3.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-1.3.0.tgz#13e75682b55518424276f7c173783456ef913d26" +doctrine@1.5.0, doctrine@^1.2.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" dependencies: esutils "^2.0.2" isarray "^1.0.0" -doctrine@^1.2.2: - version "1.5.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" +doctrine@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" dependencies: esutils "^2.0.2" - isarray "^1.0.0" ecc-jsbn@~0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" dependencies: jsbn "~0.1.0" -es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.30" - resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz#7141a16836697dbabfaaaeee41495ce29f52c939" +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" dependencies: - es6-iterator "2" - es6-symbol "~3.1" + is-arrayish "^0.2.1" -es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" +es-abstract@^1.7.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: + version "0.10.37" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.37.tgz#0ee741d148b80069ba27d020393756af257defc3" + dependencies: + es6-iterator "~2.0.1" + es6-symbol "~3.1.1" + +es6-iterator@^2.0.1, es6-iterator@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" dependencies: d "1" - es5-ext "^0.10.14" - es6-symbol "^3.1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" es6-map@^0.1.3: version "0.1.5" - resolved "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" dependencies: d "1" es5-ext "~0.10.14" @@ -433,9 +674,19 @@ es6-map@^0.1.3: es6-symbol "~3.1.1" event-emitter "~0.3.5" -es6-set@^0.1.4, es6-set@~0.1.5: +es6-promise@^4.0.3: + version "4.2.2" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.2.tgz#f722d7769af88bd33bc13ec6605e1f92966b82d9" + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + dependencies: + es6-promise "^4.0.3" + +es6-set@~0.1.5: version "0.1.5" - resolved "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" dependencies: d "1" es5-ext "~0.10.14" @@ -443,119 +694,119 @@ es6-set@^0.1.4, es6-set@~0.1.5: es6-symbol "3.1.1" event-emitter "~0.3.5" -es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1: +es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" dependencies: d "1" es5-ext "~0.10.14" es6-weak-map@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" dependencies: d "1" es5-ext "^0.10.14" es6-iterator "^2.0.1" es6-symbol "^3.1.1" -escape-string-regexp@1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -escodegen@1.8.x: - version "1.8.1" - resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" escope@^3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" dependencies: es6-map "^0.1.3" es6-weak-map "^2.0.1" esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-config-airbnb-base@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-3.0.1.tgz#b777e01f65e946933442b499fc8518aa251a6530" +eslint-config-standard-jsx@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/eslint-config-standard-jsx/-/eslint-config-standard-jsx-4.0.2.tgz#009e53c4ddb1e9ee70b4650ffe63a7f39f8836e1" -eslint-config-airbnb@^9.0.1: - version "9.0.1" - resolved "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-9.0.1.tgz#6708170d5034b579d52913fe49dee2f7fec7d894" - dependencies: - eslint-config-airbnb-base "^3.0.0" +eslint-config-standard@10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" eslint-import-resolver-node@^0.2.0: version "0.2.3" - resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" dependencies: debug "^2.2.0" object-assign "^4.0.1" resolve "^1.1.6" -eslint-plugin-import@^1.11.1: - version "1.16.0" - resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-1.16.0.tgz#b2fa07ebcc53504d0f2a4477582ec8bff1871b9f" +eslint-module-utils@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" + dependencies: + debug "^2.6.8" + pkg-dir "^1.0.0" + +eslint-plugin-import@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e" dependencies: builtin-modules "^1.1.1" contains-path "^0.1.0" debug "^2.2.0" - doctrine "1.3.x" - es6-map "^0.1.3" - es6-set "^0.1.4" + doctrine "1.5.0" eslint-import-resolver-node "^0.2.0" + eslint-module-utils "^2.0.0" has "^1.0.1" lodash.cond "^4.3.0" - lodash.endswith "^4.0.1" - lodash.find "^4.3.0" - lodash.findindex "^4.3.0" minimatch "^3.0.3" - object-assign "^4.0.1" - pkg-dir "^1.0.0" pkg-up "^1.0.0" -eslint-plugin-jsx-a11y@1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-1.2.0.tgz#b1382dedb35b173a0ff444f2bc67bd37b10906d9" +eslint-plugin-node@~4.2.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-4.2.3.tgz#c04390ab8dbcbb6887174023d6f3a72769e63b97" dependencies: + ignore "^3.0.11" + minimatch "^3.0.2" object-assign "^4.0.1" + resolve "^1.1.7" + semver "5.3.0" + +eslint-plugin-promise@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca" -eslint-plugin-react@^5.2.2: - version "5.2.2" - resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz#7db068e1f5487f6871e4deef36a381c303eac161" +eslint-plugin-react@~6.10.0: + version "6.10.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz#c5435beb06774e12c7db2f6abaddcbf900cd3f78" dependencies: + array.prototype.find "^2.0.1" doctrine "^1.2.2" - jsx-ast-utils "^1.2.1" + has "^1.0.1" + jsx-ast-utils "^1.3.4" + object.assign "^4.0.4" -eslint@2.13.1: - version "2.13.1" - resolved "https://registry.npmjs.org/eslint/-/eslint-2.13.1.tgz#e4cc8fa0f009fb829aaae23855a29360be1f6c11" +eslint-plugin-standard@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" + +eslint@~3.19.0: + version "3.19.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" dependencies: + babel-code-frame "^6.16.0" chalk "^1.1.3" - concat-stream "^1.4.6" + concat-stream "^1.5.2" debug "^2.1.1" - doctrine "^1.2.2" - es6-map "^0.1.3" + doctrine "^2.0.0" escope "^3.6.0" - espree "^3.1.6" + espree "^3.4.0" + esquery "^1.0.0" estraverse "^4.2.0" esutils "^2.0.2" - file-entry-cache "^1.1.1" + file-entry-cache "^2.0.0" glob "^7.0.3" - globals "^9.2.0" - ignore "^3.1.2" + globals "^9.14.0" + ignore "^3.2.0" imurmurhash "^0.1.4" inquirer "^0.12.0" is-my-json-valid "^2.10.0" @@ -565,130 +816,234 @@ eslint@2.13.1: levn "^0.3.0" lodash "^4.0.0" mkdirp "^0.5.0" - optionator "^0.8.1" - path-is-absolute "^1.0.0" + natural-compare "^1.4.0" + optionator "^0.8.2" path-is-inside "^1.0.1" pluralize "^1.2.1" progress "^1.1.8" require-uncached "^1.0.2" - shelljs "^0.6.0" - strip-json-comments "~1.0.1" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~2.0.1" table "^3.7.8" text-table "~0.2.0" user-home "^2.0.0" -espree@^3.1.6: - version "3.5.1" - resolved "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz#0c988b8ab46db53100a1954ae4ba995ddd27d87e" +espree@^3.4.0: + version "3.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca" dependencies: - acorn "^5.1.1" + acorn "^5.2.1" acorn-jsx "^3.0.0" -esprima@2.7.x, esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - esprima@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" dependencies: estraverse "^4.1.0" object-assign "^4.0.1" -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" esutils@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" event-emitter@~0.3.5: version "0.3.5" - resolved "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" dependencies: d "1" es5-ext "~0.10.14" +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + exit-hook@^1.0.0: version "1.1.1" - resolved "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" -extend@3, extend@~3.0.0, extend@~3.0.1: +extend@~3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +external-editor@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48" + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" -extsprintf@1.3.0, extsprintf@^1.2.0: +extsprintf@1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" fast-deep-equal@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" fast-levenshtein@~2.0.4: version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" figures@^1.3.5: version "1.7.0" - resolved "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" dependencies: escape-string-regexp "^1.0.5" object-assign "^4.1.0" -file-entry-cache@^1.1.1: - version "1.3.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8" +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +find-cache-dir@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + dependencies: + commondir "^1.0.1" + mkdirp "^0.5.1" + pkg-dir "^1.0.0" + +find-root@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + find-up@^1.0.0: version "1.1.2" - resolved "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + flat-cache@^1.2.1: version "1.3.0" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" dependencies: circular-json "^0.3.1" del "^2.0.2" graceful-fs "^4.1.2" write "^0.2.1" +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +foreground-child@^1.5.3, foreground-child@^1.5.6: + version "1.5.6" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" + dependencies: + cross-spawn "^4" + signal-exit "^3.0.0" + forever-agent@~0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" form-data@~2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" dependencies: asynckit "^0.4.0" combined-stream "^1.0.5" mime-types "^2.1.12" -formatio@1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" +formatio@1.2.0, formatio@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb" dependencies: - samsam "~1.1" + samsam "1.x" -"fs-extra@>= 0.6.0": - version "4.0.2" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b" +"fs-extra@>= 0.6.0", fs-extra@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -696,49 +1051,60 @@ formatio@1.1.1: fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -function-bind@^1.0.2: +function-bind@^1.0.2, function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" generate-function@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" generate-object-property@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" dependencies: is-property "^1.0.0" +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + +get-stdin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + getpass@^0.1.1: version "0.1.7" - resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" dependencies: assert-plus "^1.0.0" -glob@3.2.3: - version "3.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz#e313eeb249c7affaa5c475286b0e115b59839467" +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" dependencies: - graceful-fs "~2.0.0" - inherits "2" - minimatch "~0.2.11" + glob-parent "^2.0.0" + is-glob "^2.0.0" -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" + is-glob "^2.0.0" -glob@^7.0.3, glob@^7.0.5: +glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6: version "7.1.2" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -747,13 +1113,13 @@ glob@^7.0.3, glob@^7.0.5: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^9.2.0: +globals@^9.14.0, globals@^9.18.0: version "9.18.0" - resolved "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" globby@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" dependencies: array-union "^1.0.1" arrify "^1.0.0" @@ -762,21 +1128,17 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -graceful-fs@^4.1.2, graceful-fs@^4.1.6: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -graceful-fs@~2.0.0: - version "2.0.3" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz#7cd2cdb228a4a3f36e95efa6cc142de7d1a136d0" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -growl@1.8.1: - version "1.8.1" - resolved "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz#4b2dec8d907e93db336624dcec0183502f8c9428" +growl@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" -handlebars@^4.0.1: - version "4.0.10" - resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" +handlebars@^4.0.3: + version "4.0.11" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" dependencies: async "^1.4.0" optimist "^0.6.1" @@ -786,106 +1148,105 @@ handlebars@^4.0.1: har-schema@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" har-validator@~5.0.3: version "5.0.3" - resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" dependencies: ajv "^5.1.0" har-schema "^2.0.0" has-ansi@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" has@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" dependencies: function-bind "^1.0.2" hawk@~6.0.2: version "6.0.2" - resolved "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" dependencies: boom "4.x.x" cryptiles "3.x.x" hoek "4.x.x" sntp "2.x.x" +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + "highlight.js@>= 8.0.x": version "9.12.0" - resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" hoek@4.x.x: version "4.2.0" - resolved "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + +hosted-git-info@^2.1.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" http-signature@~1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -https-proxy-agent@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6" +https-proxy-agent@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz#a7ce4382a1ba8266ee848578778122d491260fd9" dependencies: - agent-base "2" - debug "2" - extend "3" + agent-base "^4.1.0" + debug "^3.1.0" -husky@^0.14.3: - version "0.14.3" - resolved "https://registry.yarnpkg.com/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3" - dependencies: - is-ci "^1.0.10" - normalize-path "^1.0.0" - strip-indent "^2.0.0" +iconv-lite@^0.4.17: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -ignore@^3.1.2: - version "3.3.5" - resolved "https://registry.npmjs.org/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6" +ignore@^3.0.11, ignore@^3.0.9, ignore@^3.2.0: + version "3.3.7" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" dependencies: once "^1.3.0" wrappy "1" inherits@2, inherits@^2.0.3, inherits@~2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - -ini@~1.3.0: - version "1.3.4" - resolved "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" inquirer@^0.12.0: version "0.12.0" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" dependencies: ansi-escapes "^1.1.0" ansi-regex "^2.0.0" @@ -901,366 +1262,678 @@ inquirer@^0.12.0: strip-ansi "^3.0.0" through "^2.3.6" +inquirer@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +interpret@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + +invariant@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + is-buffer@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" -is-ci@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e" +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" dependencies: - ci-info "^1.0.0" + number-is-nan "^1.0.0" is-fullwidth-code-point@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" is-my-json-valid@^2.10.0: - version "2.16.1" - resolved "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz#5a846777e2c2620d1e69104e5d3a03b1f6088f11" + version "2.17.1" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" dependencies: generate-function "^2.0.0" generate-object-property "^1.1.0" jsonpointer "^4.0.0" xtend "^4.0.0" +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + is-path-cwd@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" is-path-in-cwd@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" dependencies: is-path-inside "^1.0.0" is-path-inside@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" dependencies: path-is-inside "^1.0.1" +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + is-property@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" -is-resolvable@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" dependencies: - tryit "^1.0.1" + has "^1.0.1" + +is-resolvable@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.1.tgz#acca1cd36dbe44b974b924321555a70ba03b1cf4" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" is-typedarray@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" -isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -isemail@1.x.x: - version "1.2.0" - resolved "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" isstream@~0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -istanbul@^0.4.5: - version "0.4.5" - resolved "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - dependencies: - abbrev "1.0.x" - async "1.x" - escodegen "1.8.x" - esprima "2.7.x" - glob "^5.0.15" - handlebars "^4.0.1" - js-yaml "3.x" - mkdirp "0.5.x" - nopt "3.x" - once "1.x" - resolve "1.1.x" - supports-color "^3.1.0" - which "^1.1.1" - wordwrap "^1.0.0" - -jade@0.26.3: - version "0.26.3" - resolved "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" - dependencies: - commander "0.6.1" - mkdirp "0.3.0" - -joi@^6.9.1: - version "6.10.1" - resolved "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" - dependencies: - hoek "2.x.x" - isemail "1.x.x" - moment "2.x.x" - topo "1.x.x" - -js-yaml@3.x, js-yaml@^3.5.1: + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +istanbul-lib-coverage@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" + +istanbul-lib-hook@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz#8538d970372cb3716d53e55523dd54b557a8d89b" + dependencies: + append-transform "^0.4.0" + +istanbul-lib-instrument@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz#250b30b3531e5d3251299fdd64b0b2c9db6b558e" + dependencies: + babel-generator "^6.18.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.18.0" + istanbul-lib-coverage "^1.1.1" + semver "^5.3.0" + +istanbul-lib-report@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.2.tgz#922be27c13b9511b979bd1587359f69798c1d425" + dependencies: + istanbul-lib-coverage "^1.1.1" + mkdirp "^0.5.1" + path-parse "^1.0.5" + supports-color "^3.1.2" + +istanbul-lib-source-maps@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.2.tgz#750578602435f28a0c04ee6d7d9e0f2960e62c1c" + dependencies: + debug "^3.1.0" + istanbul-lib-coverage "^1.1.1" + mkdirp "^0.5.1" + rimraf "^2.6.1" + source-map "^0.5.3" + +istanbul-reports@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.3.tgz#3b9e1e8defb6d18b1d425da8e8b32c5a163f2d10" + dependencies: + handlebars "^4.0.3" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.5.1: version "3.10.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" dependencies: argparse "^1.0.7" esprima "^4.0.0" jsbn@~0.1.0: version "0.1.1" - resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +json-parse-better-errors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" json-schema-traverse@^0.3.0: version "0.3.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" json-schema@0.2.3: version "0.2.3" - resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" dependencies: jsonify "~0.0.0" json-stringify-safe@~5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" jsonfile@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" optionalDependencies: graceful-fs "^4.1.6" jsonify@~0.0.0: version "0.0.0" - resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" jsonpointer@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" jsprim@^1.2.2: version "1.4.1" - resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" dependencies: assert-plus "1.0.0" extsprintf "1.3.0" json-schema "0.2.3" verror "1.10.0" -jsx-ast-utils@^1.2.1: +jsx-ast-utils@^1.3.4: version "1.4.1" - resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1" + +just-extend@^1.1.26: + version "1.1.27" + resolved "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" kind-of@^3.0.2: version "3.2.2" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" dependencies: is-buffer "^1.1.5" lazy-cache@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" levn@^0.3.0, levn@~0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + lodash.cond@^4.3.0: version "4.5.2" - resolved "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" - -lodash.endswith@^4.0.1: - version "4.2.1" - resolved "https://registry.npmjs.org/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09" + resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" -lodash.find@^4.3.0: - version "4.6.0" - resolved "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" -lodash.findindex@^4.3.0: - version "4.6.0" - resolved "https://registry.npmjs.org/lodash.findindex/-/lodash.findindex-4.6.0.tgz#a3245dee61fb9b6e0624b535125624bb69c11106" +lodash@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.0.0, lodash@^4.13.1, lodash@^4.3.0: +lodash@^4.0.0, lodash@^4.13.1, lodash@^4.17.4, lodash@^4.3.0: version "4.17.4" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lolex@^1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" -lolex@1.3.2: - version "1.3.2" - resolved "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" +lolex@^2.2.0: + version "2.3.1" + resolved "https://registry.npmjs.org/lolex/-/lolex-2.3.1.tgz#3d2319894471ea0950ef64692ead2a5318cff362" longest@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +loose-envify@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" -lru-cache@2: - version "2.7.3" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" +lru-cache@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" "marked@>= 0.2.7": - version "0.3.6" - resolved "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" + version "0.3.9" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.9.tgz#54ce6a57e720c3ac6098374ec625fcbcc97ff290" + +md5-hex@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" + dependencies: + md5-o-matic "^0.1.1" + +md5-o-matic@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + +merge-source-map@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" + dependencies: + source-map "^0.6.1" + +micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" mime-db@~1.30.0: version "1.30.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" mime-types@^2.1.12, mime-types@~2.1.17: version "2.1.17" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: mime-db "~1.30.0" -"minimatch@2 || 3", minimatch@^3.0.3, minimatch@^3.0.4: +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + +minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: brace-expansion "^1.1.7" -minimatch@~0.2.11: - version "0.2.14" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - minimist@0.0.8: version "0.0.8" - resolved "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@^1.2.0: +minimist@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" minimist@~0.0.1: version "0.0.10" - resolved "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" -mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" -mocha@2.4.5: - version "2.4.5" - resolved "https://registry.npmjs.org/mocha/-/mocha-2.4.5.tgz#151768dd2875eb51bc8295e9800026e9f2bb398f" - dependencies: - commander "2.3.0" - debug "2.2.0" - diff "1.4.0" - escape-string-regexp "1.0.2" - glob "3.2.3" - growl "1.8.1" - jade "0.26.3" +mocha@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" + dependencies: + browser-stdout "1.3.0" + commander "2.11.0" + debug "3.1.0" + diff "3.3.1" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.3" + he "1.1.1" mkdirp "0.5.1" - supports-color "1.2.0" - -moment@2.x.x: - version "2.18.1" - resolved "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" - -ms@0.7.1: - version "0.7.1" - resolved "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + supports-color "4.4.0" ms@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -mustache@^2.2.1: - version "2.3.0" - resolved "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" mute-stream@0.0.5: version "0.0.5" - resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" -nodesecurity-npm-utils@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-5.0.0.tgz#05aa30de30ca8c845c4048e94fd78e5e08b55ed9" +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" -nopt@3.x: - version "3.0.6" - resolved "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" +nise@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/nise/-/nise-1.2.0.tgz#079d6cadbbcb12ba30e38f1c999f36ad4d6baa53" dependencies: - abbrev "1" + formatio "^1.2.0" + just-extend "^1.1.26" + lolex "^1.6.0" + path-to-regexp "^1.7.0" + text-encoding "^0.6.4" -normalize-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" +nodesecurity-npm-utils@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/nodesecurity-npm-utils/-/nodesecurity-npm-utils-6.0.0.tgz#5fb5974008c0c97a5c01844faa8fd3fc5520806c" -nsp@^2.6.3: - version "2.8.1" - resolved "https://registry.npmjs.org/nsp/-/nsp-2.8.1.tgz#436e3f13869e0610d3a38f59d55f9b353cc32817" +normalize-package-data@^2.3.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" dependencies: - chalk "^1.1.1" - cli-table "^0.3.1" - cvss "^1.0.0" - https-proxy-agent "^1.0.0" - joi "^6.9.1" - nodesecurity-npm-utils "^5.0.0" - path-is-absolute "^1.0.0" - rc "^1.1.2" - semver "^5.0.3" - subcommand "^2.0.3" - wreck "^6.3.0" + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +nsp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/nsp/-/nsp-3.1.0.tgz#e3d168b01258728ef1cb03fea9ec4f0059c8e3f3" + dependencies: + chalk "^2.1.0" + cli-table2 "^0.2.0" + cvss "^1.0.2" + https-proxy-agent "^2.1.0" + inquirer "^3.3.0" + nodesecurity-npm-utils "^6.0.0" + semver "^5.4.1" + wreck "^12.5.1" + yargs "^9.0.1" number-is-nan@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +nyc@^11.4.1: + version "11.4.1" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.4.1.tgz#13fdf7e7ef22d027c61d174758f6978a68f4f5e5" + dependencies: + archy "^1.0.0" + arrify "^1.0.1" + caching-transform "^1.0.0" + convert-source-map "^1.3.0" + debug-log "^1.0.1" + default-require-extensions "^1.0.0" + find-cache-dir "^0.1.1" + find-up "^2.1.0" + foreground-child "^1.5.3" + glob "^7.0.6" + istanbul-lib-coverage "^1.1.1" + istanbul-lib-hook "^1.1.0" + istanbul-lib-instrument "^1.9.1" + istanbul-lib-report "^1.1.2" + istanbul-lib-source-maps "^1.2.2" + istanbul-reports "^1.1.3" + md5-hex "^1.2.0" + merge-source-map "^1.0.2" + micromatch "^2.3.11" + mkdirp "^0.5.0" + resolve-from "^2.0.0" + rimraf "^2.5.4" + signal-exit "^3.0.1" + spawn-wrap "^1.4.2" + test-exclude "^4.1.1" + yargs "^10.0.3" + yargs-parser "^8.0.0" oauth-sign@~0.8.2: version "0.8.2" - resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-keys@^1.0.11, object-keys@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" -once@1.x, once@^1.3.0: +object.assign@^4.0.4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +once@^1.3.0: version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: wrappy "1" onetime@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" optimist@^0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: minimist "~0.0.1" wordwrap "~0.0.2" -optionator@^0.8.1: +optionator@^0.8.2: version "0.8.2" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" @@ -1269,94 +1942,235 @@ optionator@^0.8.1: type-check "~0.3.2" wordwrap "~1.0.0" -os-homedir@^1.0.0: +os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-limit@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" path-exists@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" dependencies: pinkie-promise "^2.0.0" +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" path-is-inside@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" path-parse@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +pathval@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" performance-now@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" pify@^2.0.0: version "2.3.0" - resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" pinkie-promise@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" - resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-conf@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-2.1.0.tgz#2126514ca6f2abfebd168596df18ba57867f0058" + dependencies: + find-up "^2.0.0" + load-json-file "^4.0.0" + +pkg-config@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pkg-config/-/pkg-config-1.1.1.tgz#557ef22d73da3c8837107766c52eadabde298fe4" + dependencies: + debug-log "^1.0.0" + find-root "^1.0.0" + xtend "^4.0.1" pkg-dir@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" dependencies: find-up "^1.0.0" pkg-up@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26" dependencies: find-up "^1.0.0" pluralize@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" prelude-ls@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" process-nextick-args@~1.0.6: version "1.0.7" - resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" progress@^1.1.8: version "1.1.8" - resolved "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" punycode@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" qs@~6.5.1: version "6.5.1" - resolved "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" -rc@^1.1.2: - version "1.2.1" - resolved "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" +randomatic@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" dependencies: - deep-extend "~0.4.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" + is-number "^3.0.0" + kind-of "^4.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" readable-stream@^2.2.2: version "2.3.3" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -1368,19 +2182,49 @@ readable-stream@^2.2.2: readline2@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" mute-stream "0.0.5" +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + repeat-string@^1.5.2: version "1.6.1" - resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" request-promise-core@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" dependencies: lodash "^4.13.1" @@ -1394,7 +2238,7 @@ request-promise-native@^1.0.5: request@^2.83.0: version "2.83.0" - resolved "https://registry.npmjs.org/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" dependencies: aws-sign2 "~0.7.0" aws4 "^1.6.0" @@ -1419,130 +2263,209 @@ request@^2.83.0: tunnel-agent "^0.6.0" uuid "^3.1.0" +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + require-uncached@^1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" resolve-from@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" -resolve@1.1.x: - version "1.1.7" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" +resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" -resolve@^1.1.6: - version "1.4.0" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" +resolve@^1.1.6, resolve@^1.1.7: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" dependencies: path-parse "^1.0.5" restore-cursor@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" dependencies: exit-hook "^1.0.0" onetime "^1.0.0" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + right-align@^0.1.1: version "0.1.3" - resolved "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" dependencies: align-text "^0.1.1" -rimraf@^2.2.8: +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: version "2.6.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: glob "^7.0.5" run-async@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" dependencies: once "^1.3.0" +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" + +run-parallel@^1.1.2: + version "1.1.6" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.6.tgz#29003c9a2163e01e2d2dfc90575f2c6c1d61a039" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + rx-lite@^3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -samsam@1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" - -samsam@~1.1: - version "1.1.3" - resolved "https://registry.npmjs.org/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" +samsam@1.x: + version "1.3.0" + resolved "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" -semver@^5.0.3: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1: version "5.4.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" -semver@~5.0.1: - version "5.0.3" - resolved "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" +semver@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" -shelljs@^0.6.0: - version "0.6.1" - resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" -sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +shelljs@^0.7.5: + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" sinon-chai@^2.8.0: version "2.14.0" - resolved "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz#da7dd4cc83cd6a260b67cca0f7a9fdae26a1205d" + resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.14.0.tgz#da7dd4cc83cd6a260b67cca0f7a9fdae26a1205d" -sinon@1.17.3: - version "1.17.3" - resolved "https://registry.npmjs.org/sinon/-/sinon-1.17.3.tgz#44d64bc748d023880046c1543cefcea34c47d17e" +sinon@^4.1.3: + version "4.1.4" + resolved "https://registry.npmjs.org/sinon/-/sinon-4.1.4.tgz#36bb237bae38ddf9cc92dcc1b16c51e7785bbc9c" dependencies: - formatio "1.1.1" - lolex "1.3.2" - samsam "1.1.2" - util ">=0.10.3 <1" + diff "^3.1.0" + formatio "1.2.0" + lodash.get "^4.4.2" + lolex "^2.2.0" + nise "^1.2.0" + supports-color "^4.4.0" + type-detect "^4.0.5" slice-ansi@0.0.4: version "0.0.4" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + +slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" sntp@2.x.x: - version "2.0.2" - resolved "https://registry.npmjs.org/sntp/-/sntp-2.0.2.tgz#5064110f0af85f7cfdb7d6b67a40028ce52b4b2b" + version "2.1.0" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" dependencies: hoek "4.x.x" source-map@^0.4.4: version "0.4.4" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" dependencies: amdefine ">=0.0.4" -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" +source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +spawn-wrap@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.2.tgz#cff58e73a8224617b6561abdc32586ea0c82248c" dependencies: - amdefine ">=0.0.4" + foreground-child "^1.5.6" + mkdirp "^0.5.0" + os-homedir "^1.0.1" + rimraf "^2.6.2" + signal-exit "^3.0.2" + which "^1.3.0" -source-map@~0.5.1: - version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: version "1.13.1" - resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -1554,85 +2477,113 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" +standard-engine@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/standard-engine/-/standard-engine-7.0.0.tgz#ebb77b9c8fc2c8165ffa353bd91ba0dff41af690" + dependencies: + deglob "^2.1.0" + get-stdin "^5.0.1" + minimist "^1.1.0" + pkg-conf "^2.0.0" + +standard@^10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/standard/-/standard-10.0.3.tgz#7869bcbf422bdeeaab689a1ffb1fea9677dd50ea" + dependencies: + eslint "~3.19.0" + eslint-config-standard "10.2.1" + eslint-config-standard-jsx "4.0.2" + eslint-plugin-import "~2.2.0" + eslint-plugin-node "~4.2.2" + eslint-plugin-promise "~3.5.0" + eslint-plugin-react "~6.10.0" + eslint-plugin-standard "~3.0.1" + standard-engine "~7.0.0" + stealthy-require@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" string-width@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0: +string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" string_decoder@~1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" dependencies: safe-buffer "~5.1.0" stringstream@~0.0.5: version "0.0.5" - resolved "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" -strip-ansi@^3.0.0: +strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" dependencies: ansi-regex "^3.0.0" -strip-indent@^2.0.0: +strip-bom@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" -strip-json-comments@~1.0.1: - version "1.0.4" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" strip-json-comments@~2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -subcommand@^2.0.3: - version "2.1.0" - resolved "https://registry.npmjs.org/subcommand/-/subcommand-2.1.0.tgz#5e4ceca5a3779e3365b1511e05f866877302f760" +supports-color@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" dependencies: - cliclopts "^1.1.0" - debug "^2.1.3" - minimist "^1.2.0" - xtend "^4.0.0" - -supports-color@1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" + has-flag "^2.0.0" supports-color@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^3.1.0: +supports-color@^3.1.2: version "3.2.3" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: has-flag "^1.0.0" +supports-color@^4.0.0, supports-color@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + table@^3.7.8: version "3.8.3" - resolved "https://registry.npmjs.org/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" dependencies: ajv "^4.7.0" ajv-keywords "^1.0.0" @@ -1641,65 +2592,79 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" +test-exclude@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" + dependencies: + arrify "^1.0.1" + micromatch "^2.3.11" + object-assign "^4.1.0" + read-pkg-up "^1.0.1" + require-main-filename "^1.0.1" + +text-encoding@^0.6.4: + version "0.6.4" + resolved "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + text-table@~0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" through@^2.3.6: version "2.3.8" - resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" -topo@1.x.x: - version "1.1.0" - resolved "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5" +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" dependencies: - hoek "2.x.x" + os-tmpdir "~1.0.2" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" tough-cookie@>=2.3.3, tough-cookie@~2.3.3: version "2.3.3" - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" dependencies: punycode "^1.4.1" -tryit@^1.0.1: - version "1.0.3" - resolved "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" tunnel-agent@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" dependencies: safe-buffer "^5.0.1" tv4@^1.2.7: version "1.3.0" - resolved "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz#d020c846fadd50c855abb25ebaecc68fc10f7963" + resolved "https://registry.yarnpkg.com/tv4/-/tv4-1.3.0.tgz#d020c846fadd50c855abb25ebaecc68fc10f7963" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" - resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" type-check@~0.3.2: version "0.3.2" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" dependencies: prelude-ls "~1.1.2" -type-detect@0.1.1: - version "0.1.1" - resolved "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" - -type-detect@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.5.tgz#d70e5bc81db6de2a381bcaca0c6e0cbdc7635de2" typedarray@^0.0.6: version "0.0.6" - resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" uglify-js@^2.6: version "2.8.29" - resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -1708,90 +2673,169 @@ uglify-js@^2.6: uglify-to-browserify@~1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" "underscore@>= 1.0.0": version "1.8.3" - resolved "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" universalify@^0.1.0: version "0.1.1" - resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" user-home@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" dependencies: os-homedir "^1.0.0" util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -"util@>=0.10.3 <1": - version "0.10.3" - resolved "https://registry.npmjs.org/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - dependencies: - inherits "2.0.1" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" uuid@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" + +validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" verror@1.10.0: version "1.10.0" - resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" -which@^1.1.1: +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + +which@^1.2.9, which@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" dependencies: isexe "^2.0.0" window-size@0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" wordwrap@0.0.2: version "0.0.2" - resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - -wordwrap@^1.0.0, wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" wordwrap@~0.0.2: version "0.0.3" - resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" wrappy@1: version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +wreck@^12.5.1: + version "12.5.1" + resolved "https://registry.yarnpkg.com/wreck/-/wreck-12.5.1.tgz#cd2ffce167449e1f0242ed9cf80552e20fb6902a" + dependencies: + boom "5.x.x" + hoek "4.x.x" -wreck@^6.3.0: - version "6.3.0" - resolved "https://registry.npmjs.org/wreck/-/wreck-6.3.0.tgz#a1369769f07bbb62d6a378336a7871fc773c740b" +write-file-atomic@^1.1.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" dependencies: - boom "2.x.x" - hoek "2.x.x" + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" write@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" dependencies: mkdirp "^0.5.1" -xtend@^4.0.0: +xtend@^4.0.0, xtend@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + dependencies: + camelcase "^4.1.0" + +yargs-parser@^8.0.0, yargs-parser@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + dependencies: + camelcase "^4.1.0" + +yargs@^10.0.3: + version "10.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.0.tgz#85d98f2264c7487f18c4607b79c7e4e3b160e69e" + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^8.1.0" + +yargs@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" yargs@~3.10.0: version "3.10.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" dependencies: camelcase "^1.0.2" cliui "^2.1.0"