├── .circleci ├── config.yml └── run-build-locally.sh ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .vscode └── launch.json ├── Gruntfile.js ├── README.md ├── package.json ├── repo.json ├── scripts ├── check-plugins.js ├── check-repo-update.js ├── checkSemver.js ├── diffPluginsRepo.js ├── github │ └── github.js ├── lint-plugin.js ├── lint-pr.js ├── lint-repo-update.js ├── lint-repo.js ├── lintPlugin.js └── lintRepoUpdate.js └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Javascript Node CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details 4 | # 5 | aliases: 6 | # Workflow filters 7 | - &filter-not-release-or-master 8 | tags: 9 | ignore: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/ 10 | branches: 11 | ignore: 12 | - master 13 | - &filter-only-master 14 | branches: 15 | only: master 16 | 17 | version: 2 18 | jobs: 19 | build: 20 | docker: 21 | - image: circleci/node:8 22 | working_directory: ~/repo 23 | steps: 24 | - checkout 25 | - restore_cache: 26 | keys: 27 | - dependency-cache-{{ checksum "yarn.lock" }} 28 | # fallback to using the latest cache if no exact match is found 29 | - dependency-cache- 30 | - run: 31 | name: yarn install 32 | command: 'yarn install --pure-lockfile --no-progress' 33 | - save_cache: 34 | paths: 35 | - node_modules 36 | key: dependency-cache-{{ checksum "yarn.lock" }} 37 | - run: yarn lint-repo 38 | 39 | check-repo-update: 40 | docker: 41 | - image: circleci/node:8 42 | working_directory: ~/repo 43 | steps: 44 | - checkout 45 | - restore_cache: 46 | keys: 47 | - dependency-cache-{{ checksum "yarn.lock" }} 48 | - dependency-cache- 49 | - run: 50 | name: yarn install 51 | command: 'yarn install --pure-lockfile --no-progress' 52 | - save_cache: 53 | paths: 54 | - node_modules 55 | key: dependency-cache-{{ checksum "yarn.lock" }} 56 | - run: 57 | name: check-repo-update 58 | command: node ./scripts/check-repo-update.js 59 | 60 | lint-updated-plugins: 61 | docker: 62 | - image: circleci/node:8 63 | working_directory: ~/repo 64 | steps: 65 | - checkout 66 | - restore_cache: 67 | keys: 68 | - dependency-cache-{{ checksum "yarn.lock" }} 69 | - dependency-cache- 70 | - run: 71 | name: yarn install 72 | command: 'yarn install --pure-lockfile --no-progress' 73 | - save_cache: 74 | paths: 75 | - node_modules 76 | key: dependency-cache-{{ checksum "yarn.lock" }} 77 | - run: 78 | name: lint-updated-plugins 79 | command: node ./scripts/lint-repo-update.js 80 | 81 | workflows: 82 | version: 2 83 | build-master: 84 | jobs: 85 | - build: 86 | filters: *filter-only-master 87 | 88 | build-branches-and-prs: 89 | jobs: 90 | - check-repo-update: 91 | filters: *filter-not-release-or-master 92 | - lint-updated-plugins: 93 | filters: *filter-not-release-or-master 94 | # - build: 95 | # filters: *filter-not-release-or-master 96 | -------------------------------------------------------------------------------- /.circleci/run-build-locally.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | BASEDIR=$(dirname "$0") 3 | 4 | CURRENT_COMMIT_HASH=$(git log -n 1 | grep -Po "(?<=commit )[0-9a-z]{40}") 5 | CURRENT_BRANCH=$(git status | grep -Po "(?<=On branch ).+") 6 | 7 | COMMIT_HASH=${2:-${CURRENT_COMMIT_HASH}} 8 | BRANCH=${1:-${CURRENT_BRANCH}} 9 | 10 | echo "Branch: ${BRANCH} commit: ${COMMIT_HASH}" 11 | 12 | curl --user ${CIRCLE_TOKEN}: \ 13 | --request POST \ 14 | --form revision=${CURRENT_COMMIT_HASH}\ 15 | --form config=${BASEDIR}/config.yml \ 16 | --form notify=false \ 17 | https://circleci.com/api/v1.1/project/github/grafana/grafana-plugin-repository/tree/${CURRENT_BRANCH} 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **IMPORTANT:** THIS REPOSITORY IS DEPRECATED. 2 | 3 | We no longer accept new plugin submissions through this repository. Instead we invite you to submit your plugin directly from your Grafana Cloud account! 4 | 5 | For more information, refer to the [README](https://github.com/grafana/grafana-plugin-repository/blob/master/README.md). 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | .idea 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "lint-repo", 11 | "skipFiles": [ 12 | "/**" 13 | ], 14 | "program": "${workspaceFolder}/scripts/lint-repo.js", 15 | "cwd": "${workspaceFolder}" 16 | }, 17 | { 18 | "type": "node", 19 | "request": "launch", 20 | "name": "lint-repo-update", 21 | "skipFiles": [ 22 | "/**" 23 | ], 24 | "program": "${workspaceFolder}/scripts/lint-repo-update.js", 25 | "cwd": "${workspaceFolder}" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | const request = require('request'); 2 | const semver = require('semver'); 3 | 4 | module.exports = function(grunt) { 5 | 6 | grunt.registerTask('default', 'Lint all the plugins', function() { 7 | var done = this.async(); 8 | 9 | var repo = grunt.file.readJSON('repo.json'); 10 | 11 | let completedLints = 0; 12 | let failedLints = 0; 13 | 14 | for (var i = 0; i < repo.plugins.length; i++) { 15 | let commit; 16 | 17 | if (repo.plugins[i].versions.length === 1) { 18 | commit = repo.plugins[i].versions[0].commit; 19 | } else { 20 | // use the top or bottom commit which has the highest version 21 | // can't sort with semver as lots of plugins don't follow it 22 | const topCommit = repo.plugins[i].versions[0]; 23 | const bottomCommit = repo.plugins[i].versions[repo.plugins[i].versions.length-1]; 24 | commit = semver.gte(topCommit.version, bottomCommit.version) ? topCommit.commit: bottomCommit.commit; 25 | } 26 | 27 | const postData = { 28 | url: repo.plugins[i].url.trim(), 29 | commit: commit.trim() 30 | }; 31 | 32 | request.post({url:'https://grafana.com/api/plugins/lint', form: postData}, function(err, httpResponse, body){ 33 | completedLints++; 34 | 35 | const parsedBody = JSON.parse(body); 36 | 37 | if (!parsedBody.valid) { 38 | grunt.log.writeln(parsedBody.url + ' : ' + parsedBody.commit + '. FAIL: ' + JSON.stringify(parsedBody.lintErrors)).error().writeln(); 39 | failedLints++; 40 | } else { 41 | grunt.log.writeln(JSON.stringify(parsedBody.url + ' : ' + parsedBody.commit)).ok().writeln(); 42 | } 43 | 44 | if (completedLints === repo.plugins.length - 1) { 45 | done(failedLints === 0); 46 | } 47 | }); 48 | } 49 | }); 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Community plugins 2 | 3 | We originally created this repository years ago to accept plugin submissions from the Grafana community. With more than 150 plugins now published, it has become obvious that the community plugins are instrumental in Grafana's success. Due to this, we've make the process of submitting plugins easier. 4 | 5 | You can now [submit](#submit-your-plugin) and [maintain your plugin](#maintain-your-plugin) directly from your Grafana Cloud account! 6 | 7 | This also means that we're starting the process of deprecating this repository. Here's how it affects you: 8 | 9 | - If your pull request has been triaged by us already and is waiting for review, you don't need to do anything. We'll continue to review the remaining plugin submissions in the pipeline. 10 | - If you'd like, you can migrate your current plugin submission by submitting it through the new submission flow. Let us know that you'd like to use the new flow by updating your pull request. Please keep the pull request open to keep your position in the review queue. 11 | - If you're submitting a new plugin or an update to an existing plugin, please use the new submission flow. We won't accept any new plugin submissions on this repository. 12 | 13 | If you have any questions, [create a new issue](https://github.com/grafana/grafana-plugin-repository/issues/new), or send an email to `plugin-reviews@grafana.com`. 14 | 15 | ## Submit your plugin 16 | 17 | Before you submit your plugin, we ask that you read our [guidelines](#guidelines) and [frequently asked questions](#faq). 18 | 19 | Screenshot 2021-08-25 at 12 31 32@2x 20 | 21 | 1. [Sign in](https://grafana.com/auth/sign-in) to your Grafana Cloud account. 22 | 1. In the left menu, under **Org settings**, click **My Plugins**. 23 | 1. Click **Submit Plugin**. 24 | 1. Enter the information requested by the form. 25 | - **OS & Architecture:** 26 | - Select **Single** if your plugin archive contains binaries for multiple architectures. 27 | - Select **Multiple** if you'd like to submit separate plugin archives for each architecture. This can lead to faster downloads since users can select the specific architecture on which they want to install the plugin. 28 | - **URL:** A URL that points to a ZIP archive of your packaged plugin. 29 | - **MD5:** The MD5 hash of the plugin specified by the **URL**. 30 | - The remaining questions help us determine the [signature level](https://grafana.com/docs/grafana/latest/plugins/plugin-signatures/#plugin-signature-levels) for your plugin. 31 | 1. Click **Submit**. 32 | 33 | After you have submitted your plugin, we run an automated validation to make sure it adheres to our guidelines. Once your submission passes the validation, it's placed in a review queue. 34 | 35 | All submissions are manually inspected by a plugin reviewer. For every new plugin, we perform a manual review that includes the following checks: 36 | 37 | - **Code review:** For quality and security purposes, we review the source code for the plugin. If you're unable to make the source code publicly available, let us know in a comment on your plugin submission. 38 | - **Tests:** We install your plugin on one of our Grafana instances to test it for basic use. For more advanced plugins, we may ask you to assist us in configuring a test environment for the plugin. This test environment will be used whenever you submit an plugin update. 39 | 40 | ## Maintain your plugin 41 | 42 | To submit an update for an already published plugin: 43 | 44 | 1. [Sign in](https://grafana.com/auth/sign-in) to your Grafana Cloud account. 45 | 1. In the left menu, under **Org settings**, click **My Plugins**. 46 | 1. Click **Submit Update** for the plugin you want to update. 47 | 1. Enter the information requested by the form. 48 | - **OS & Architecture:** 49 | - Select **Single** if your plugin archive contains binaries for multiple architectures. 50 | - Select **Multiple** if you'd like to submit separate plugin archives for each architecture. This can lead to faster downloads since users can select the specific architecture they want to install the plugin on. 51 | - **URL:** A URL that points to a ZIP archive of your packaged plugin. 52 | - **MD5:** The MD5 hash of the plugin specified by the **URL**. 53 | 1. Click **Submit**. 54 | 55 | ## Guidelines 56 | 57 | To speed up the time it takes to review your plugin: 58 | 59 | - Check that your plugin is ready for review using the [plugin validator](https://plugin-validator.grafana.net). 60 | - Read our [6 tips for improving your Grafana plugin before you publish](https://grafana.com/blog/2021/01/21/6-tips-for-improving-your-grafana-plugin-before-you-publish/) 61 | 62 | ## FAQ 63 | 64 | - **Do I need to submit a private plugin?:** No. Please only submit plugins that you wish to make publicly available for the Grafana community. 65 | - **How long does it take to review my submission?:** We're not able to give an estimate at this time, though we're constantly working on improving the time it takes to review a plugin. 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grafana-plugin-repository", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "repository": "git@github.com:grafana/grafana-plugin-repository.git", 6 | "author": "Daniel Lee ", 7 | "license": "MIT", 8 | "scripts": { 9 | "lint": "grunt", 10 | "lint-repo": "./scripts/lint-repo.js", 11 | "lint-repo-update": "./scripts/lint-repo-update.js", 12 | "test-ci-build": "./.circleci/run-build-locally.sh" 13 | }, 14 | "devDependencies": { 15 | "chalk": "^2.4.2", 16 | "grunt": "^1.0.3", 17 | "lodash": "^4.17.21", 18 | "request": "^2.88.0", 19 | "request-promise-native": "^1.0.7", 20 | "semver": "^5.4.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /scripts/check-plugins.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const chalk = require('chalk'); 5 | 6 | // const prettyjson = require('prettyjson'); 7 | 8 | // const repo = require('../repo.json'); 9 | const repoPath = path.join(__dirname, '../repo.json'); 10 | let repo = fs.readFileSync(repoPath); 11 | try { 12 | repo = JSON.parse(repo); 13 | } catch (parseError) { 14 | console.error(chalk.red('Error parsing repo.json')) 15 | console.error(parseError); 16 | process.exit(1); 17 | } 18 | 19 | // console.log(prettyjson.render(repo)); 20 | // console.log(repo); 21 | const plugins = repo.plugins.map(plugin => plugin.id); 22 | // console.log(plugins); 23 | console.log(repo.plugins[1]); 24 | -------------------------------------------------------------------------------- /scripts/check-repo-update.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const request = require('request-promise-native'); 3 | const { diffPluginsRepo } = require('./diffPluginsRepo'); 4 | const { checkSemver } = require('./checkSemver'); 5 | 6 | const repoMasterUrl = 'https://raw.githubusercontent.com/grafana/grafana-plugin-repository/master/repo.json'; 7 | const repoCurrent = require('../repo.json'); 8 | 9 | function main() { 10 | return request(repoMasterUrl).then(body => { 11 | const repoMaster = JSON.parse(body); 12 | const diff = diffPluginsRepo(repoCurrent, repoMaster); 13 | return { diff, repoMaster }; 14 | }).then(result => { 15 | const { diff, repoMaster } = result; 16 | console.log(JSON.stringify(diff, null, 2)); 17 | return checkSemver(diff, repoMaster); 18 | }).catch(error => { 19 | console.error(error); 20 | process.exit(1); 21 | }); 22 | } 23 | 24 | main(); 25 | -------------------------------------------------------------------------------- /scripts/checkSemver.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | const semver = require('semver'); 3 | 4 | /** 5 | * Checks whether plugin updates follow semver or not. 6 | * @param {*} diff 7 | * @param {*} base 8 | */ 9 | function checkSemver(diff, base) { 10 | _.forEach(diff.diff, (pluginUpdate, pluginId) => { 11 | _.forEach(pluginUpdate.versions, versionObj => { 12 | const updateVersion = versionObj.version; 13 | if (!semver.valid(updateVersion)) { 14 | throw new Error(`Invalid version: ${updateVersion} (plugin: ${pluginId})`); 15 | } 16 | const basePlugin = _.find(base.plugins, { 'id': pluginId }); 17 | if (basePlugin) { 18 | 19 | const baseVersions = basePlugin.versions; 20 | _.forEach(baseVersions, baseVersionObj => { 21 | const baseVersion = baseVersionObj.version; 22 | if (semver.lt(updateVersion, baseVersion)) { 23 | throw new Error(`Updated version should be greater than previous: ${updateVersion} < ${baseVersion} (plugin: ${pluginId})`); 24 | } 25 | }); 26 | } 27 | }); 28 | }); 29 | return true; 30 | } 31 | 32 | module.exports = { 33 | checkSemver 34 | }; 35 | -------------------------------------------------------------------------------- /scripts/diffPluginsRepo.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | 3 | /** 4 | * Returns plugins repo diff with additional metadata. 5 | * @param {Object} update updated repo 6 | * @param {Object} base base repo 7 | * @return {Object} Diff object 8 | */ 9 | function diffPluginsRepo(update, base) { 10 | let diff = {}; 11 | let diffMeta = {}; 12 | 13 | const pluginsBase = _.keyBy(base.plugins, 'id'); 14 | const pluginsUpdate = _.keyBy(update.plugins, 'id'); 15 | 16 | _.forEach(pluginsUpdate, (pluginUpdate, id) => { 17 | const pluginBase = pluginsBase[id]; 18 | 19 | // New plugin added 20 | if (!pluginBase) { 21 | diff[id] = pluginUpdate; 22 | diffMeta[id] = { newPlugin: true }; 23 | return; 24 | } 25 | 26 | // Plugin version added 27 | if (!_.isEqual(pluginUpdate, pluginBase)) { 28 | diff[id] = {}; 29 | diffMeta[id] = { updatedPlugin: true }; 30 | 31 | // Check if metadata was changed 32 | _.forOwn(pluginUpdate, (value, key) => { 33 | if (value !== pluginBase[key] && key !== 'versions') { 34 | diffMeta[id].metadataUpdated = true; 35 | diff[key] = value; 36 | } 37 | }); 38 | 39 | let versionsDiff = _.xorWith(pluginUpdate.versions, pluginBase.versions, _.isEqual); 40 | if (versionsDiff && versionsDiff.length) { 41 | diff[id].versions = []; 42 | // Check if version was changed 43 | versionsDiff.forEach(versionObj => { 44 | const changedVersion = _.find(pluginBase.versions, { 'version': versionObj.version }); 45 | if (changedVersion) { 46 | diffMeta[id].versionChanged = true; 47 | const versionChange = _.find(pluginUpdate.versions, { 'version': versionObj.version }); 48 | if (versionChange && !_.find(diff[id].versions, { 'version': versionChange.version })) { 49 | diff[id].versions.push(versionChange); 50 | _.forOwn(changedVersion, (value, key) => { 51 | if (value !== versionObj[key]) { 52 | if (diffMeta[id].versionChanges && diffMeta[id].versionChanges[versionObj.version]) { 53 | diffMeta[id].versionChanges[versionObj.version].push(key); 54 | } else { 55 | diffMeta[id].versionChanges = { 56 | [versionObj.version]: [key] 57 | }; 58 | } 59 | } 60 | }); 61 | } 62 | } else { 63 | diff[id].versions.push(versionObj); 64 | diffMeta[id].versionAdded = true; 65 | } 66 | }); 67 | } 68 | } 69 | }); 70 | return { 71 | diff: diff, 72 | meta: diffMeta 73 | }; 74 | } 75 | 76 | module.exports = { 77 | diffPluginsRepo 78 | }; 79 | -------------------------------------------------------------------------------- /scripts/github/github.js: -------------------------------------------------------------------------------- 1 | /*jshint esversion: 8 */ 2 | 3 | const request = require('request-promise-native'); 4 | const { GITHUB_API_TOKEN } = process.env; 5 | 6 | function getFileContent(owner, repo, path, commit) { 7 | let endpoint = `/repos/${owner}/${repo}/contents/${path}`; 8 | if (commit) { 9 | endpoint += `?ref=${commit}`; 10 | } 11 | return apiRequest(endpoint).then(result => { 12 | if (result && result.content) { 13 | const encoding = result.encoding || 'base64'; 14 | const content = Buffer.from(result.content, encoding).toString(); 15 | return content; 16 | } 17 | }); 18 | } 19 | 20 | async function fetchContent(url) { 21 | const result = await _request(url); 22 | if (result && result.content) { 23 | const encoding = result.encoding || 'base64'; 24 | const content = Buffer.from(result.content, encoding).toString(); 25 | return content; 26 | } else { 27 | return null; 28 | } 29 | } 30 | 31 | async function fetchPRFile(owner, repo, pr, filename) { 32 | const endpont = `/repos/${owner}/${repo}/pulls/${pr}/files`; 33 | const prFiles = await apiRequest(endpont); 34 | for (const prFile of prFiles) { 35 | if (prFile.filename === filename) { 36 | const contentUrl = prFile.contents_url; 37 | const content = await fetchContent(contentUrl); 38 | return content; 39 | } 40 | } 41 | throw new Error('File not found'); 42 | } 43 | 44 | function fetchFile({base, commit, path, prefix}) { 45 | // try to match base as a github repo url 46 | const matches = new RegExp('^https?://github[.]com/([^/]+)/([^/]+)(?:/tree/([^/]+))?(.*)$').exec(base); 47 | 48 | // couldn't match the base 49 | if (!matches) { 50 | throw new Error('Could not extract repo and owner from url'); 51 | } 52 | 53 | // build github contents api url 54 | const owner = matches[1]; 55 | const repo = matches[2]; 56 | const baseRef = matches[3]; 57 | const basePath = matches[4]; 58 | 59 | let filePath = basePath; 60 | if (prefix) { 61 | filePath += '/' + prefix; 62 | } 63 | filePath += '/' + path; 64 | if (filePath[0] === '/') { 65 | filePath = filePath.slice(1); 66 | } 67 | 68 | if (!commit && baseRef) { 69 | commit = baseRef; 70 | } 71 | 72 | return getFileContent(owner, repo, filePath, commit); 73 | } 74 | 75 | async function fetchJson({base, commit, path, prefix}) { 76 | const content = await fetchFile({base, commit, path, prefix}); 77 | try { 78 | const json = JSON.parse(content); 79 | return json; 80 | } catch(parseErr) { 81 | return Promise.reject(parseErr); 82 | } 83 | } 84 | 85 | async function fetchPluginJson(url, commit) { 86 | let json; 87 | 88 | for (const prefix of ['dist', '', 'src']) { 89 | try { 90 | json = await fetchJson({ base: url, commit, path: 'plugin.json', prefix }); 91 | return { json, prefix }; 92 | } catch(err) { 93 | // Skip errors for first two prefixes 94 | if (prefix === 'src') { 95 | throw new Error(err.message); 96 | } 97 | } 98 | } 99 | 100 | throw new Error('Could not find plugin.json'); 101 | } 102 | 103 | function apiRequest(endpoint) { 104 | const githubApiUrl = 'https://api.github.com'; 105 | const url = `${githubApiUrl}${endpoint}`; 106 | return _request(url); 107 | } 108 | 109 | function _request(url) { 110 | const options = { 111 | uri: url, 112 | headers: { 113 | 'User-Agent': 'NodeJS' 114 | }, 115 | json: true 116 | }; 117 | if (GITHUB_API_TOKEN) { 118 | options.headers['Authorization'] = `token ${GITHUB_API_TOKEN}`; 119 | } 120 | return request(options); 121 | } 122 | 123 | module.exports = { 124 | getFileContent, 125 | fetchPluginJson, 126 | fetchPRFile, 127 | request: apiRequest, 128 | }; 129 | -------------------------------------------------------------------------------- /scripts/lint-plugin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const chalk = require('chalk'); 3 | const { lintPlugin } = require('./lintPlugin'); 4 | 5 | const pluginUrl = process.argv[2]; 6 | const commit = process.argv[3]; 7 | let version, pluginId; 8 | if (process.argv.length > 4) { 9 | version = process.argv[4]; 10 | } 11 | if (process.argv.length > 5) { 12 | pluginId = process.argv[5]; 13 | } 14 | 15 | console.log(`${pluginUrl} : ${commit}`); 16 | 17 | return lintPlugin(pluginUrl, commit, version, download, pluginId).then(result => { 18 | // console.debug(result); 19 | if (result && result.statusCode > 0) { 20 | console.error(chalk.yellow(result.status)); 21 | result.warnings.forEach(err => console.error(chalk.yellow(err))); 22 | } else { 23 | console.log(chalk.green(result.status)); 24 | } 25 | }).catch(error => { 26 | if (error && error.status === 'Error') { 27 | console.error(chalk.red(error.status)); 28 | error.errors.forEach(err => console.error(chalk.red(err))); 29 | error.warnings.forEach(err => console.error(chalk.yellow(err))); 30 | process.exit(1); 31 | } else { 32 | console.error(error.message || error); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /scripts/lint-pr.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const request = require('request-promise-native'); 3 | const chalk = require('chalk'); 4 | const github = require('./github/github'); 5 | const { lintRepoUpdate } = require('./lintRepoUpdate'); 6 | 7 | async function main() { 8 | if (process.argv.length < 3) { 9 | printUsage(); 10 | return; 11 | } 12 | let prNumber = process.argv[2]; 13 | prNumber = prNumber[0] === '#' ? prNumber.slice(1) : prNumber; 14 | try { 15 | const repoJson = await getPluginsRepoPR(prNumber); 16 | return await lintRepoUpdate(repoJson); 17 | } catch(err) { 18 | console.log(chalk.red('Error: '), err.error || err.message || err); 19 | process.exit(1); 20 | } 21 | } 22 | 23 | async function getPluginsRepoPR(prNumber) { 24 | const repoJsonFile = await github.fetchPRFile('grafana', 'grafana-plugin-repository', prNumber, 'repo.json'); 25 | try { 26 | const repoJson = JSON.parse(repoJsonFile); 27 | return repoJson; 28 | } catch(parseError) { 29 | throw new Error(`Error parsing repo.json from PR: ${parseError}`); 30 | } 31 | } 32 | 33 | function printUsage() { 34 | console.log(`Lint plugins from particular pull request 35 | Usage: 36 | ./lint-pr.js 37 | ./lint-pr.js 42`); 38 | } 39 | 40 | main(); 41 | -------------------------------------------------------------------------------- /scripts/lint-repo-update.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const { lintRepoUpdate } = require('./lintRepoUpdate'); 3 | 4 | const repoCurrent = require('../repo.json'); 5 | 6 | async function main() { 7 | return lintRepoUpdate(repoCurrent); 8 | } 9 | 10 | main().catch(console.error); 11 | -------------------------------------------------------------------------------- /scripts/lint-repo.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /*jshint esversion: 8 */ 3 | 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | const _ = require('lodash'); 7 | const semver = require('semver'); 8 | const chalk = require('chalk'); 9 | const { lintPlugin } = require('./lintPlugin'); 10 | 11 | const grafanaSlugPattern = /^(grafana|raintank)-/; 12 | 13 | async function main(options) { 14 | let pluginsRepo; 15 | try { 16 | pluginsRepo = getRepo(); 17 | } catch(err) { 18 | console.error(chalk.red('Error processing repo.json')); 19 | console.error(err); 20 | process.exit(1); 21 | } 22 | const plugins = pluginsRepo.plugins; 23 | if (!(plugins && plugins.length)) { 24 | console.log(chalk.yellow('Warning: repo.json is empty')); 25 | } 26 | 27 | let okLints = 0; 28 | let failedLints = 0; 29 | let warningLints = 0; 30 | 31 | for (const plugin of plugins) { 32 | let version; 33 | 34 | if (options.skipGrafana && plugin.id.match(grafanaSlugPattern)) { 35 | console.log(`Info: skipping plugin ${chalk.blue(plugin.id)}\n`); 36 | continue; 37 | } 38 | 39 | if (!(plugin.versions && plugin.versions.length)) { 40 | console.log(chalk.yellow(`Warning: plugin ${plugin.id} has no versions`)); 41 | continue; 42 | } 43 | 44 | if (plugin.versions.length === 1) { 45 | version = plugin.versions[0]; 46 | } else { 47 | // use the top or bottom commit which has the highest version 48 | // can't sort with semver as lots of plugins don't follow it 49 | const topVersion = plugin.versions[0]; 50 | const bottomVersion = plugin.versions[plugin.versions.length - 1]; 51 | version = semver.gte(topVersion.version, bottomVersion.version) ? topVersion : bottomVersion; 52 | } 53 | 54 | let commit = version.commit; 55 | let url = version.url; 56 | let download = version.download || null; 57 | 58 | // console.log(`Linting plugin ${chalk.blue(plugin.id)}`); 59 | console.log(`Linting ${chalk.blue(plugin.id)} version ${chalk.blue(version.version)}`); 60 | try { 61 | const lintResult = await lintPlugin(url, commit, version.version, download, plugin.id); 62 | if (lintResult) { 63 | if (lintResult && lintResult.statusCode > 0) { 64 | console.error(chalk.yellow(lintResult.status)); 65 | lintResult.warnings.forEach(err => console.error(chalk.yellow(err))); 66 | warningLints++; 67 | } else { 68 | console.log(chalk.green(lintResult.status)); 69 | okLints++; 70 | } 71 | } 72 | console.log(''); 73 | } catch(error) { 74 | console.log(`${url} : ${commit}`); 75 | if (error && error.status === 'Error') { 76 | console.error(chalk.red(error.status)); 77 | error.errors.forEach(err => console.error(chalk.red(err))); 78 | error.warnings.forEach(err => console.error(chalk.yellow(err))); 79 | } else { 80 | console.error(error); 81 | } 82 | failedLints++; 83 | console.log(''); 84 | } 85 | } 86 | 87 | console.log(chalk.green('Status:')); 88 | console.log(`${chalk.green('OK')}: ${okLints}`); 89 | console.log(`${chalk.yellow('Warnings')}: ${warningLints}`); 90 | console.log(`${chalk.red('Failed')}: ${failedLints}`); 91 | 92 | if (failedLints > 0) { 93 | process.exit(1); 94 | } 95 | } 96 | 97 | function getRepo() { 98 | const repoPath = path.join(__dirname, '../repo.json'); 99 | let repo = fs.readFileSync(repoPath); 100 | repo = JSON.parse(repo); 101 | return repo; 102 | } 103 | 104 | let options = {}; 105 | for (let i = 2; i < process.argv.length; i++) { 106 | const arg = process.argv[i]; 107 | if (arg === '--skip-grafana' || arg === '-s') { 108 | options.skipGrafana = true; 109 | } 110 | } 111 | 112 | main(options); 113 | -------------------------------------------------------------------------------- /scripts/lintPlugin.js: -------------------------------------------------------------------------------- 1 | /*jshint esversion: 8 */ 2 | const request = require('request-promise-native'); 3 | const semver = require('semver'); 4 | const { fetchPluginJson } = require('./github/github'); 5 | const chalk = require('chalk'); 6 | 7 | const PLUGIN_TYPES = ['datasource', 'panel', 'app', 'renderer']; 8 | const PLUGIN_ID_PATTERN = new RegExp(`^[a-z0-9]+(-[a-z0-9]+)*-(${PLUGIN_TYPES.join('|')})$`); 9 | 10 | async function lintPlugin(url, commit, version, download, pluginId) { 11 | const postData = { 12 | url: url, 13 | commit: commit 14 | }; 15 | if (download) { 16 | postData.download = download; 17 | } 18 | 19 | const apiResponse = await request.post({ url: 'https://grafana.com/api/plugins/lint', form: postData }); 20 | // console.debug(apiResponse); 21 | const linterResult = JSON.parse(apiResponse); 22 | 23 | const result = { 24 | status: 'OK', 25 | statusCode: 0, 26 | errors: [], 27 | warnings: [], 28 | }; 29 | 30 | if (!linterResult.valid) { 31 | if (linterResult.lintErrors && linterResult.lintErrors.length) { 32 | const htmlTagsErrorPattern = /The .* file contains HTML tags/; 33 | linterResult.lintErrors.forEach(err => { 34 | // Do not fail on "The README.md file contains HTML tags" error 35 | if (htmlTagsErrorPattern.test(err)) { 36 | result.status = 'Warning'; 37 | result.statusCode = 1; 38 | result.warnings.push(err); 39 | } else { 40 | result.status = 'Error'; 41 | result.statusCode = 2; 42 | result.errors.push(err); 43 | } 44 | }); 45 | } else { 46 | result.status = 'Error'; 47 | result.statusCode = 2; 48 | } 49 | } 50 | 51 | if (pluginId) { 52 | try { 53 | const publishedVersion = await getPublishedVersion(pluginId); 54 | if (semver.gt(publishedVersion, version)) { 55 | addWarning(`Published version (${publishedVersion}) newer than repo.json (${version})`, result); 56 | } 57 | 58 | // Check if Org exist for new plugins 59 | if (!publishedVersion) { 60 | const slug = getOrgSlug(pluginId); 61 | try { 62 | const org = await getOrg(slug); 63 | } catch (error) { 64 | addWarning(error, result); 65 | } 66 | } 67 | } catch (err) { } 68 | } 69 | 70 | // if the linter from api is valid, and there is no commit returned, this is a zip-style plugin 71 | if (linterResult.commit === '') { 72 | console.log(`Plugin ${chalk.blue(pluginId)} version ${chalk.blue(version)} published with download url to zip, skipping dist check.`); 73 | } else { 74 | // Try to fetch plugin.json and make some additional checks 75 | try { 76 | const pluginJsonResponse = await fetchPluginJson(url, commit); 77 | const pluginJson = pluginJsonResponse.json; 78 | // console.log(pluginJson); 79 | if (pluginJsonResponse.prefix === 'src') { 80 | addWarning(`It seems, plugin isn't built properly: plugin.json found in src/ only`, result); 81 | } 82 | 83 | if (pluginId !== pluginJson.id) { 84 | addWarning(`Plugin id in repo.json (${pluginId}) doesn't match plugin.json (${pluginJson.id})`, result); 85 | } 86 | 87 | if (!pluginJson.id) { 88 | addError('No plugin id found in plugin.json', result); 89 | } 90 | 91 | // Plugin id rules 92 | const validSlug = PLUGIN_ID_PATTERN.test(pluginJson.id); 93 | if (!validSlug) { 94 | addError(`Invalid plugin id "${pluginJson.id}" found in plugin.json`, result); 95 | } 96 | 97 | // TODO this check is duplicated in https://grafana.com/api/plugins/lint 98 | // Plugin type rules 99 | if (!PLUGIN_TYPES.includes(pluginJson.type)) { 100 | addError(`Invalid plugin type - must be one of: datasource, panel or app, got "${pluginJson.type}"`, result); 101 | } 102 | 103 | const pluginJsonVersion = pluginJson.info.version; 104 | if (version && (!pluginJsonVersion || pluginJsonVersion !== version)) { 105 | addWarning(`Version in repo.json (${version}) doesn't match plugin.json (${pluginJsonVersion})`, result); 106 | } 107 | 108 | if (!(pluginJson.info.author && pluginJson.info.author.name)) { 109 | addWarning(`No author specified in plugin.json`, result); 110 | } 111 | 112 | if (!pluginJson.info.description) { 113 | addWarning(`No plugin description provided in plugin.json`, result); 114 | } 115 | } catch (err) { 116 | console.log(`Warning: failed fetching plugin.json. This may be caused by private repo without proper access rights.`); 117 | } 118 | } 119 | 120 | if (result.statusCode < 2) { 121 | return result; 122 | } else { 123 | return Promise.reject(result); 124 | } 125 | } 126 | 127 | async function getPublishedVersion(pluginId) { 128 | try { 129 | let plugin = await request.get(`https://grafana.com/api/plugins/${pluginId}`); 130 | plugin = JSON.parse(plugin); 131 | return plugin.version; 132 | } catch (err) { 133 | // console.log(err.error || err.message || err); 134 | throw new Error(`Warning: unable to fetch published plugin ${pluginId}`); 135 | } 136 | } 137 | 138 | async function getOrg(orgSlug) { 139 | try { 140 | let result = await request.get(`https://grafana.com/api/orgs/${orgSlug}`); 141 | result = JSON.parse(result); 142 | return result; 143 | } catch (err) { 144 | // console.log(err.error || err.message || err); 145 | let error = {}; 146 | try { 147 | error = JSON.parse(err.error); 148 | } catch (jsonErr) { } 149 | 150 | throw new Error(`Unable to get organization ${orgSlug}, ${error.message || ''}`); 151 | } 152 | } 153 | 154 | function getOrgSlug(pluginId) { 155 | const result = /^([a-z0-9]+)(-[a-z0-9]+)*-(datasource|app|panel)$/.exec(pluginId); 156 | if (result && result.length > 1) { 157 | return result[1]; 158 | } 159 | return null; 160 | } 161 | 162 | function addWarning(warning, result) { 163 | result.warnings.push(warning); 164 | if (result.statusCode < 1) { 165 | result.status = 'Warning'; 166 | result.statusCode = 1; 167 | } 168 | } 169 | 170 | function addError(error, result) { 171 | result.errors.push(error); 172 | if (result.statusCode < 2) { 173 | result.status = 'Error'; 174 | result.statusCode = 2; 175 | } 176 | } 177 | 178 | module.exports = { 179 | lintPlugin 180 | }; 181 | -------------------------------------------------------------------------------- /scripts/lintRepoUpdate.js: -------------------------------------------------------------------------------- 1 | /*jshint esversion: 8 */ 2 | 3 | const _ = require('lodash'); 4 | const chalk = require('chalk'); 5 | const request = require('request-promise-native'); 6 | const { diffPluginsRepo } = require('./diffPluginsRepo'); 7 | const { lintPlugin } = require('./lintPlugin'); 8 | 9 | async function lintRepoUpdate(repoCurrent, repoMasterUrl) { 10 | repoMasterUrl = repoMasterUrl || 'https://raw.githubusercontent.com/grafana/grafana-plugin-repository/master/repo.json'; 11 | return request(repoMasterUrl).then(body => { 12 | const repoMaster = JSON.parse(body); 13 | try { 14 | const diff = diffPluginsRepo(repoCurrent, repoMaster); 15 | return diff; 16 | } catch(diffError) { 17 | console.log(diffError); 18 | process.exit(1); 19 | } 20 | }).then(result => { 21 | const diff = result; 22 | return lintRepoDiff(diff); 23 | }).catch(error => { 24 | console.error(error.message ? chalk.red(error.message) : error); 25 | process.exit(1); 26 | }); 27 | } 28 | 29 | function lintRepoDiff(diff) { 30 | let success = true; 31 | let promises = []; 32 | _.forEach(diff.diff, (pluginUpdate, pluginId) => { 33 | _.forEach(pluginUpdate.versions, async versionObj => { 34 | const url = versionObj.url.trim(); 35 | let commit = versionObj.commit || null; 36 | // commit is not required for zip releases 37 | if (commit) { 38 | commit = versionObj.commit.trim(); 39 | } 40 | const version = versionObj.version; 41 | let download = versionObj.download || null; 42 | 43 | const lintPromise = lintPlugin(url, commit, version, download, pluginId).then(result => { 44 | console.log(`Linting ${chalk.blue(pluginId)} version ${chalk.blue(versionObj.version)}`); 45 | if (commit) { 46 | console.log(`${url} ${commit}`); 47 | } else { 48 | console.log(`${url} (uses download url)`); 49 | } 50 | if (result && result.statusCode > 0) { 51 | console.error(chalk.yellow(result.status)); 52 | result.warnings.forEach(err => console.error(chalk.yellow(err))); 53 | } else { 54 | console.log(chalk.green(result.status)); 55 | } 56 | console.log(''); 57 | return; 58 | }).catch(error => { 59 | console.log(`Linting ${chalk.blue(pluginId)} version ${chalk.blue(versionObj.version)}`); 60 | console.log(`${url} ${commit}`); 61 | if (error && error.status === 'Error') { 62 | console.error(chalk.red(error.status)); 63 | error.errors.forEach(err => console.error(chalk.red(err))); 64 | error.warnings.forEach(err => console.error(chalk.yellow(err))); 65 | } else { 66 | console.error(error); 67 | } 68 | console.log(''); 69 | success = false; 70 | return; 71 | }); 72 | promises.push(lintPromise); 73 | }); 74 | }); 75 | 76 | if (promises.length === 0) { 77 | console.log('No plugins to lint'); 78 | } 79 | 80 | return Promise.all(promises).then(() => { 81 | if (success) { 82 | return success; 83 | } else { 84 | return Promise.reject(new Error('Failed linting plugins update')); 85 | } 86 | }); 87 | } 88 | 89 | module.exports = { 90 | lintRepoUpdate, 91 | lintRepoDiff, 92 | }; 93 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | abbrev@1: 6 | version "1.1.1" 7 | resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" 8 | integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== 9 | 10 | ajv@^6.5.5: 11 | version "6.10.1" 12 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.1.tgz#ebf8d3af22552df9dd049bfbe50cc2390e823593" 13 | integrity sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ== 14 | dependencies: 15 | fast-deep-equal "^2.0.1" 16 | fast-json-stable-stringify "^2.0.0" 17 | json-schema-traverse "^0.4.1" 18 | uri-js "^4.2.2" 19 | 20 | ansi-styles@^3.2.1: 21 | version "3.2.1" 22 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 23 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 24 | dependencies: 25 | color-convert "^1.9.0" 26 | 27 | argparse@^1.0.7: 28 | version "1.0.10" 29 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 30 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 31 | dependencies: 32 | sprintf-js "~1.0.2" 33 | 34 | array-find-index@^1.0.1: 35 | version "1.0.2" 36 | resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" 37 | integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= 38 | 39 | asn1@~0.2.3: 40 | version "0.2.4" 41 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" 42 | integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== 43 | dependencies: 44 | safer-buffer "~2.1.0" 45 | 46 | assert-plus@1.0.0, assert-plus@^1.0.0: 47 | version "1.0.0" 48 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 49 | integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= 50 | 51 | async@~1.5.2: 52 | version "1.5.2" 53 | resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 54 | integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= 55 | 56 | asynckit@^0.4.0: 57 | version "0.4.0" 58 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 59 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 60 | 61 | aws-sign2@~0.7.0: 62 | version "0.7.0" 63 | resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" 64 | integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= 65 | 66 | aws4@^1.8.0: 67 | version "1.8.0" 68 | resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" 69 | integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== 70 | 71 | balanced-match@^1.0.0: 72 | version "1.0.0" 73 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 74 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 75 | 76 | bcrypt-pbkdf@^1.0.0: 77 | version "1.0.2" 78 | resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" 79 | integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= 80 | dependencies: 81 | tweetnacl "^0.14.3" 82 | 83 | brace-expansion@^1.1.7: 84 | version "1.1.11" 85 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 86 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 87 | dependencies: 88 | balanced-match "^1.0.0" 89 | concat-map "0.0.1" 90 | 91 | camelcase-keys@^2.0.0: 92 | version "2.1.0" 93 | resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" 94 | integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= 95 | dependencies: 96 | camelcase "^2.0.0" 97 | map-obj "^1.0.0" 98 | 99 | camelcase@^2.0.0: 100 | version "2.1.1" 101 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" 102 | integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= 103 | 104 | caseless@~0.12.0: 105 | version "0.12.0" 106 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 107 | integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= 108 | 109 | chalk@^2.4.2, chalk@~2.4.1: 110 | version "2.4.2" 111 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 112 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 113 | dependencies: 114 | ansi-styles "^3.2.1" 115 | escape-string-regexp "^1.0.5" 116 | supports-color "^5.3.0" 117 | 118 | coffeescript@~1.10.0: 119 | version "1.10.0" 120 | resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.10.0.tgz#e7aa8301917ef621b35d8a39f348dcdd1db7e33e" 121 | integrity sha1-56qDAZF+9iGzXYo580jc3R234z4= 122 | 123 | color-convert@^1.9.0: 124 | version "1.9.3" 125 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 126 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 127 | dependencies: 128 | color-name "1.1.3" 129 | 130 | color-name@1.1.3: 131 | version "1.1.3" 132 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 133 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 134 | 135 | colors@~1.1.2: 136 | version "1.1.2" 137 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" 138 | integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= 139 | 140 | combined-stream@^1.0.6, combined-stream@~1.0.6: 141 | version "1.0.8" 142 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 143 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 144 | dependencies: 145 | delayed-stream "~1.0.0" 146 | 147 | concat-map@0.0.1: 148 | version "0.0.1" 149 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 150 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 151 | 152 | core-util-is@1.0.2: 153 | version "1.0.2" 154 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 155 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 156 | 157 | currently-unhandled@^0.4.1: 158 | version "0.4.1" 159 | resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" 160 | integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= 161 | dependencies: 162 | array-find-index "^1.0.1" 163 | 164 | dashdash@^1.12.0: 165 | version "1.14.1" 166 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 167 | integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= 168 | dependencies: 169 | assert-plus "^1.0.0" 170 | 171 | dateformat@~1.0.12: 172 | version "1.0.12" 173 | resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" 174 | integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk= 175 | dependencies: 176 | get-stdin "^4.0.1" 177 | meow "^3.3.0" 178 | 179 | decamelize@^1.1.2: 180 | version "1.2.0" 181 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 182 | integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= 183 | 184 | delayed-stream@~1.0.0: 185 | version "1.0.0" 186 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 187 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 188 | 189 | ecc-jsbn@~0.1.1: 190 | version "0.1.2" 191 | resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" 192 | integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= 193 | dependencies: 194 | jsbn "~0.1.0" 195 | safer-buffer "^2.1.0" 196 | 197 | error-ex@^1.2.0: 198 | version "1.3.2" 199 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 200 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 201 | dependencies: 202 | is-arrayish "^0.2.1" 203 | 204 | escape-string-regexp@^1.0.5: 205 | version "1.0.5" 206 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 207 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 208 | 209 | esprima@^4.0.0: 210 | version "4.0.1" 211 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 212 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 213 | 214 | eventemitter2@~0.4.13: 215 | version "0.4.14" 216 | resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab" 217 | integrity sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas= 218 | 219 | exit@~0.1.1: 220 | version "0.1.2" 221 | resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" 222 | integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= 223 | 224 | extend@~3.0.2: 225 | version "3.0.2" 226 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 227 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 228 | 229 | extsprintf@1.3.0: 230 | version "1.3.0" 231 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 232 | integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= 233 | 234 | extsprintf@^1.2.0: 235 | version "1.4.0" 236 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" 237 | integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= 238 | 239 | fast-deep-equal@^2.0.1: 240 | version "2.0.1" 241 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" 242 | integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= 243 | 244 | fast-json-stable-stringify@^2.0.0: 245 | version "2.0.0" 246 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" 247 | integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= 248 | 249 | find-up@^1.0.0: 250 | version "1.1.2" 251 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" 252 | integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= 253 | dependencies: 254 | path-exists "^2.0.0" 255 | pinkie-promise "^2.0.0" 256 | 257 | findup-sync@~0.3.0: 258 | version "0.3.0" 259 | resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16" 260 | integrity sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY= 261 | dependencies: 262 | glob "~5.0.0" 263 | 264 | forever-agent@~0.6.1: 265 | version "0.6.1" 266 | resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 267 | integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= 268 | 269 | form-data@~2.3.2: 270 | version "2.3.3" 271 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" 272 | integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== 273 | dependencies: 274 | asynckit "^0.4.0" 275 | combined-stream "^1.0.6" 276 | mime-types "^2.1.12" 277 | 278 | fs.realpath@^1.0.0: 279 | version "1.0.0" 280 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 281 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 282 | 283 | get-stdin@^4.0.1: 284 | version "4.0.1" 285 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" 286 | integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= 287 | 288 | getobject@~0.1.0: 289 | version "0.1.0" 290 | resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c" 291 | integrity sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw= 292 | 293 | getpass@^0.1.1: 294 | version "0.1.7" 295 | resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 296 | integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= 297 | dependencies: 298 | assert-plus "^1.0.0" 299 | 300 | glob@^7.1.3: 301 | version "7.1.4" 302 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" 303 | integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== 304 | dependencies: 305 | fs.realpath "^1.0.0" 306 | inflight "^1.0.4" 307 | inherits "2" 308 | minimatch "^3.0.4" 309 | once "^1.3.0" 310 | path-is-absolute "^1.0.0" 311 | 312 | glob@~5.0.0: 313 | version "5.0.15" 314 | resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" 315 | integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= 316 | dependencies: 317 | inflight "^1.0.4" 318 | inherits "2" 319 | minimatch "2 || 3" 320 | once "^1.3.0" 321 | path-is-absolute "^1.0.0" 322 | 323 | glob@~7.0.0: 324 | version "7.0.6" 325 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" 326 | integrity sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo= 327 | dependencies: 328 | fs.realpath "^1.0.0" 329 | inflight "^1.0.4" 330 | inherits "2" 331 | minimatch "^3.0.2" 332 | once "^1.3.0" 333 | path-is-absolute "^1.0.0" 334 | 335 | graceful-fs@^4.1.2: 336 | version "4.2.0" 337 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" 338 | integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== 339 | 340 | grunt-cli@~1.2.0: 341 | version "1.2.0" 342 | resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.2.0.tgz#562b119ebb069ddb464ace2845501be97b35b6a8" 343 | integrity sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg= 344 | dependencies: 345 | findup-sync "~0.3.0" 346 | grunt-known-options "~1.1.0" 347 | nopt "~3.0.6" 348 | resolve "~1.1.0" 349 | 350 | grunt-known-options@~1.1.0: 351 | version "1.1.1" 352 | resolved "https://registry.yarnpkg.com/grunt-known-options/-/grunt-known-options-1.1.1.tgz#6cc088107bd0219dc5d3e57d91923f469059804d" 353 | integrity sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ== 354 | 355 | grunt-legacy-log-utils@~2.0.0: 356 | version "2.0.1" 357 | resolved "https://registry.yarnpkg.com/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz#d2f442c7c0150065d9004b08fd7410d37519194e" 358 | integrity sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA== 359 | dependencies: 360 | chalk "~2.4.1" 361 | lodash "~4.17.10" 362 | 363 | grunt-legacy-log@~2.0.0: 364 | version "2.0.0" 365 | resolved "https://registry.yarnpkg.com/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz#c8cd2c6c81a4465b9bbf2d874d963fef7a59ffb9" 366 | integrity sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw== 367 | dependencies: 368 | colors "~1.1.2" 369 | grunt-legacy-log-utils "~2.0.0" 370 | hooker "~0.2.3" 371 | lodash "~4.17.5" 372 | 373 | grunt-legacy-util@~1.1.1: 374 | version "1.1.1" 375 | resolved "https://registry.yarnpkg.com/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz#e10624e7c86034e5b870c8a8616743f0a0845e42" 376 | integrity sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A== 377 | dependencies: 378 | async "~1.5.2" 379 | exit "~0.1.1" 380 | getobject "~0.1.0" 381 | hooker "~0.2.3" 382 | lodash "~4.17.10" 383 | underscore.string "~3.3.4" 384 | which "~1.3.0" 385 | 386 | grunt@^1.0.3: 387 | version "1.0.4" 388 | resolved "https://registry.yarnpkg.com/grunt/-/grunt-1.0.4.tgz#c799883945a53a3d07622e0737c8f70bfe19eb38" 389 | integrity sha512-PYsMOrOC+MsdGEkFVwMaMyc6Ob7pKmq+deg1Sjr+vvMWp35sztfwKE7qoN51V+UEtHsyNuMcGdgMLFkBHvMxHQ== 390 | dependencies: 391 | coffeescript "~1.10.0" 392 | dateformat "~1.0.12" 393 | eventemitter2 "~0.4.13" 394 | exit "~0.1.1" 395 | findup-sync "~0.3.0" 396 | glob "~7.0.0" 397 | grunt-cli "~1.2.0" 398 | grunt-known-options "~1.1.0" 399 | grunt-legacy-log "~2.0.0" 400 | grunt-legacy-util "~1.1.1" 401 | iconv-lite "~0.4.13" 402 | js-yaml "~3.13.0" 403 | minimatch "~3.0.2" 404 | mkdirp "~0.5.1" 405 | nopt "~3.0.6" 406 | path-is-absolute "~1.0.0" 407 | rimraf "~2.6.2" 408 | 409 | har-schema@^2.0.0: 410 | version "2.0.0" 411 | resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" 412 | integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= 413 | 414 | har-validator@~5.1.0: 415 | version "5.1.3" 416 | resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" 417 | integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== 418 | dependencies: 419 | ajv "^6.5.5" 420 | har-schema "^2.0.0" 421 | 422 | has-flag@^3.0.0: 423 | version "3.0.0" 424 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 425 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 426 | 427 | hooker@~0.2.3: 428 | version "0.2.3" 429 | resolved "https://registry.yarnpkg.com/hooker/-/hooker-0.2.3.tgz#b834f723cc4a242aa65963459df6d984c5d3d959" 430 | integrity sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk= 431 | 432 | hosted-git-info@^2.1.4: 433 | version "2.8.9" 434 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" 435 | integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== 436 | 437 | http-signature@~1.2.0: 438 | version "1.2.0" 439 | resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" 440 | integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= 441 | dependencies: 442 | assert-plus "^1.0.0" 443 | jsprim "^1.2.2" 444 | sshpk "^1.7.0" 445 | 446 | iconv-lite@~0.4.13: 447 | version "0.4.24" 448 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 449 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 450 | dependencies: 451 | safer-buffer ">= 2.1.2 < 3" 452 | 453 | indent-string@^2.1.0: 454 | version "2.1.0" 455 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" 456 | integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= 457 | dependencies: 458 | repeating "^2.0.0" 459 | 460 | inflight@^1.0.4: 461 | version "1.0.6" 462 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 463 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 464 | dependencies: 465 | once "^1.3.0" 466 | wrappy "1" 467 | 468 | inherits@2: 469 | version "2.0.4" 470 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 471 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 472 | 473 | is-arrayish@^0.2.1: 474 | version "0.2.1" 475 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 476 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 477 | 478 | is-finite@^1.0.0: 479 | version "1.0.2" 480 | resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" 481 | integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= 482 | dependencies: 483 | number-is-nan "^1.0.0" 484 | 485 | is-typedarray@~1.0.0: 486 | version "1.0.0" 487 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 488 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= 489 | 490 | is-utf8@^0.2.0: 491 | version "0.2.1" 492 | resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" 493 | integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= 494 | 495 | isexe@^2.0.0: 496 | version "2.0.0" 497 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 498 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 499 | 500 | isstream@~0.1.2: 501 | version "0.1.2" 502 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 503 | integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= 504 | 505 | js-yaml@~3.13.0: 506 | version "3.13.1" 507 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 508 | integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== 509 | dependencies: 510 | argparse "^1.0.7" 511 | esprima "^4.0.0" 512 | 513 | jsbn@~0.1.0: 514 | version "0.1.1" 515 | resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 516 | integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= 517 | 518 | json-schema-traverse@^0.4.1: 519 | version "0.4.1" 520 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 521 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 522 | 523 | json-schema@0.2.3: 524 | version "0.2.3" 525 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 526 | integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= 527 | 528 | json-stringify-safe@~5.0.1: 529 | version "5.0.1" 530 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 531 | integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= 532 | 533 | jsprim@^1.2.2: 534 | version "1.4.1" 535 | resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" 536 | integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= 537 | dependencies: 538 | assert-plus "1.0.0" 539 | extsprintf "1.3.0" 540 | json-schema "0.2.3" 541 | verror "1.10.0" 542 | 543 | load-json-file@^1.0.0: 544 | version "1.1.0" 545 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" 546 | integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= 547 | dependencies: 548 | graceful-fs "^4.1.2" 549 | parse-json "^2.2.0" 550 | pify "^2.0.0" 551 | pinkie-promise "^2.0.0" 552 | strip-bom "^2.0.0" 553 | 554 | lodash@^4.17.11, lodash@^4.17.21, lodash@~4.17.10, lodash@~4.17.5: 555 | version "4.17.21" 556 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 557 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 558 | 559 | loud-rejection@^1.0.0: 560 | version "1.6.0" 561 | resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" 562 | integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= 563 | dependencies: 564 | currently-unhandled "^0.4.1" 565 | signal-exit "^3.0.0" 566 | 567 | map-obj@^1.0.0, map-obj@^1.0.1: 568 | version "1.0.1" 569 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" 570 | integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= 571 | 572 | meow@^3.3.0: 573 | version "3.7.0" 574 | resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" 575 | integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= 576 | dependencies: 577 | camelcase-keys "^2.0.0" 578 | decamelize "^1.1.2" 579 | loud-rejection "^1.0.0" 580 | map-obj "^1.0.1" 581 | minimist "^1.1.3" 582 | normalize-package-data "^2.3.4" 583 | object-assign "^4.0.1" 584 | read-pkg-up "^1.0.1" 585 | redent "^1.0.0" 586 | trim-newlines "^1.0.0" 587 | 588 | mime-db@1.40.0: 589 | version "1.40.0" 590 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" 591 | integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== 592 | 593 | mime-types@^2.1.12, mime-types@~2.1.19: 594 | version "2.1.24" 595 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" 596 | integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== 597 | dependencies: 598 | mime-db "1.40.0" 599 | 600 | "minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: 601 | version "3.0.4" 602 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 603 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 604 | dependencies: 605 | brace-expansion "^1.1.7" 606 | 607 | minimist@0.0.8: 608 | version "0.0.8" 609 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 610 | integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= 611 | 612 | minimist@^1.1.3: 613 | version "1.2.0" 614 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" 615 | integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= 616 | 617 | mkdirp@~0.5.1: 618 | version "0.5.1" 619 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 620 | integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= 621 | dependencies: 622 | minimist "0.0.8" 623 | 624 | nopt@~3.0.6: 625 | version "3.0.6" 626 | resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" 627 | integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= 628 | dependencies: 629 | abbrev "1" 630 | 631 | normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: 632 | version "2.5.0" 633 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 634 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 635 | dependencies: 636 | hosted-git-info "^2.1.4" 637 | resolve "^1.10.0" 638 | semver "2 || 3 || 4 || 5" 639 | validate-npm-package-license "^3.0.1" 640 | 641 | number-is-nan@^1.0.0: 642 | version "1.0.1" 643 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 644 | integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= 645 | 646 | oauth-sign@~0.9.0: 647 | version "0.9.0" 648 | resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" 649 | integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== 650 | 651 | object-assign@^4.0.1: 652 | version "4.1.1" 653 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 654 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 655 | 656 | once@^1.3.0: 657 | version "1.4.0" 658 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 659 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 660 | dependencies: 661 | wrappy "1" 662 | 663 | parse-json@^2.2.0: 664 | version "2.2.0" 665 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" 666 | integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= 667 | dependencies: 668 | error-ex "^1.2.0" 669 | 670 | path-exists@^2.0.0: 671 | version "2.1.0" 672 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" 673 | integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= 674 | dependencies: 675 | pinkie-promise "^2.0.0" 676 | 677 | path-is-absolute@^1.0.0, path-is-absolute@~1.0.0: 678 | version "1.0.1" 679 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 680 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 681 | 682 | path-parse@^1.0.6: 683 | version "1.0.7" 684 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 685 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 686 | 687 | path-type@^1.0.0: 688 | version "1.1.0" 689 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" 690 | integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= 691 | dependencies: 692 | graceful-fs "^4.1.2" 693 | pify "^2.0.0" 694 | pinkie-promise "^2.0.0" 695 | 696 | performance-now@^2.1.0: 697 | version "2.1.0" 698 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 699 | integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= 700 | 701 | pify@^2.0.0: 702 | version "2.3.0" 703 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 704 | integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= 705 | 706 | pinkie-promise@^2.0.0: 707 | version "2.0.1" 708 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 709 | integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= 710 | dependencies: 711 | pinkie "^2.0.0" 712 | 713 | pinkie@^2.0.0: 714 | version "2.0.4" 715 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 716 | integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= 717 | 718 | psl@^1.1.24, psl@^1.1.28: 719 | version "1.2.0" 720 | resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6" 721 | integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA== 722 | 723 | punycode@^1.4.1: 724 | version "1.4.1" 725 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" 726 | integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= 727 | 728 | punycode@^2.1.0, punycode@^2.1.1: 729 | version "2.1.1" 730 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 731 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 732 | 733 | qs@~6.5.2: 734 | version "6.5.2" 735 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" 736 | integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== 737 | 738 | read-pkg-up@^1.0.1: 739 | version "1.0.1" 740 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" 741 | integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= 742 | dependencies: 743 | find-up "^1.0.0" 744 | read-pkg "^1.0.0" 745 | 746 | read-pkg@^1.0.0: 747 | version "1.1.0" 748 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" 749 | integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= 750 | dependencies: 751 | load-json-file "^1.0.0" 752 | normalize-package-data "^2.3.2" 753 | path-type "^1.0.0" 754 | 755 | redent@^1.0.0: 756 | version "1.0.0" 757 | resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" 758 | integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= 759 | dependencies: 760 | indent-string "^2.1.0" 761 | strip-indent "^1.0.1" 762 | 763 | repeating@^2.0.0: 764 | version "2.0.1" 765 | resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" 766 | integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= 767 | dependencies: 768 | is-finite "^1.0.0" 769 | 770 | request-promise-core@1.1.2: 771 | version "1.1.2" 772 | resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" 773 | integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== 774 | dependencies: 775 | lodash "^4.17.11" 776 | 777 | request-promise-native@^1.0.7: 778 | version "1.0.7" 779 | resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59" 780 | integrity sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w== 781 | dependencies: 782 | request-promise-core "1.1.2" 783 | stealthy-require "^1.1.1" 784 | tough-cookie "^2.3.3" 785 | 786 | request@^2.88.0: 787 | version "2.88.0" 788 | resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" 789 | integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== 790 | dependencies: 791 | aws-sign2 "~0.7.0" 792 | aws4 "^1.8.0" 793 | caseless "~0.12.0" 794 | combined-stream "~1.0.6" 795 | extend "~3.0.2" 796 | forever-agent "~0.6.1" 797 | form-data "~2.3.2" 798 | har-validator "~5.1.0" 799 | http-signature "~1.2.0" 800 | is-typedarray "~1.0.0" 801 | isstream "~0.1.2" 802 | json-stringify-safe "~5.0.1" 803 | mime-types "~2.1.19" 804 | oauth-sign "~0.9.0" 805 | performance-now "^2.1.0" 806 | qs "~6.5.2" 807 | safe-buffer "^5.1.2" 808 | tough-cookie "~2.4.3" 809 | tunnel-agent "^0.6.0" 810 | uuid "^3.3.2" 811 | 812 | resolve@^1.10.0: 813 | version "1.11.1" 814 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" 815 | integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== 816 | dependencies: 817 | path-parse "^1.0.6" 818 | 819 | resolve@~1.1.0: 820 | version "1.1.7" 821 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" 822 | integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= 823 | 824 | rimraf@~2.6.2: 825 | version "2.6.3" 826 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" 827 | integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== 828 | dependencies: 829 | glob "^7.1.3" 830 | 831 | safe-buffer@^5.0.1, safe-buffer@^5.1.2: 832 | version "5.2.0" 833 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" 834 | integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== 835 | 836 | "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: 837 | version "2.1.2" 838 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 839 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 840 | 841 | "semver@2 || 3 || 4 || 5", semver@^5.4.1: 842 | version "5.7.0" 843 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" 844 | integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== 845 | 846 | signal-exit@^3.0.0: 847 | version "3.0.2" 848 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 849 | integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= 850 | 851 | spdx-correct@^3.0.0: 852 | version "3.1.0" 853 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" 854 | integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== 855 | dependencies: 856 | spdx-expression-parse "^3.0.0" 857 | spdx-license-ids "^3.0.0" 858 | 859 | spdx-exceptions@^2.1.0: 860 | version "2.2.0" 861 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" 862 | integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== 863 | 864 | spdx-expression-parse@^3.0.0: 865 | version "3.0.0" 866 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" 867 | integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== 868 | dependencies: 869 | spdx-exceptions "^2.1.0" 870 | spdx-license-ids "^3.0.0" 871 | 872 | spdx-license-ids@^3.0.0: 873 | version "3.0.5" 874 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" 875 | integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== 876 | 877 | sprintf-js@^1.0.3: 878 | version "1.1.2" 879 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" 880 | integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== 881 | 882 | sprintf-js@~1.0.2: 883 | version "1.0.3" 884 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 885 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 886 | 887 | sshpk@^1.7.0: 888 | version "1.16.1" 889 | resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" 890 | integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== 891 | dependencies: 892 | asn1 "~0.2.3" 893 | assert-plus "^1.0.0" 894 | bcrypt-pbkdf "^1.0.0" 895 | dashdash "^1.12.0" 896 | ecc-jsbn "~0.1.1" 897 | getpass "^0.1.1" 898 | jsbn "~0.1.0" 899 | safer-buffer "^2.0.2" 900 | tweetnacl "~0.14.0" 901 | 902 | stealthy-require@^1.1.1: 903 | version "1.1.1" 904 | resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" 905 | integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= 906 | 907 | strip-bom@^2.0.0: 908 | version "2.0.0" 909 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" 910 | integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= 911 | dependencies: 912 | is-utf8 "^0.2.0" 913 | 914 | strip-indent@^1.0.1: 915 | version "1.0.1" 916 | resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" 917 | integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= 918 | dependencies: 919 | get-stdin "^4.0.1" 920 | 921 | supports-color@^5.3.0: 922 | version "5.5.0" 923 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 924 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 925 | dependencies: 926 | has-flag "^3.0.0" 927 | 928 | tough-cookie@^2.3.3: 929 | version "2.5.0" 930 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" 931 | integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== 932 | dependencies: 933 | psl "^1.1.28" 934 | punycode "^2.1.1" 935 | 936 | tough-cookie@~2.4.3: 937 | version "2.4.3" 938 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" 939 | integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== 940 | dependencies: 941 | psl "^1.1.24" 942 | punycode "^1.4.1" 943 | 944 | trim-newlines@^1.0.0: 945 | version "1.0.0" 946 | resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" 947 | integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= 948 | 949 | tunnel-agent@^0.6.0: 950 | version "0.6.0" 951 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 952 | integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= 953 | dependencies: 954 | safe-buffer "^5.0.1" 955 | 956 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 957 | version "0.14.5" 958 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 959 | integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= 960 | 961 | underscore.string@~3.3.4: 962 | version "3.3.5" 963 | resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.5.tgz#fc2ad255b8bd309e239cbc5816fd23a9b7ea4023" 964 | integrity sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg== 965 | dependencies: 966 | sprintf-js "^1.0.3" 967 | util-deprecate "^1.0.2" 968 | 969 | uri-js@^4.2.2: 970 | version "4.2.2" 971 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 972 | integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== 973 | dependencies: 974 | punycode "^2.1.0" 975 | 976 | util-deprecate@^1.0.2: 977 | version "1.0.2" 978 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 979 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 980 | 981 | uuid@^3.3.2: 982 | version "3.3.2" 983 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" 984 | integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== 985 | 986 | validate-npm-package-license@^3.0.1: 987 | version "3.0.4" 988 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" 989 | integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== 990 | dependencies: 991 | spdx-correct "^3.0.0" 992 | spdx-expression-parse "^3.0.0" 993 | 994 | verror@1.10.0: 995 | version "1.10.0" 996 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 997 | integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= 998 | dependencies: 999 | assert-plus "^1.0.0" 1000 | core-util-is "1.0.2" 1001 | extsprintf "^1.2.0" 1002 | 1003 | which@~1.3.0: 1004 | version "1.3.1" 1005 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 1006 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 1007 | dependencies: 1008 | isexe "^2.0.0" 1009 | 1010 | wrappy@1: 1011 | version "1.0.2" 1012 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1013 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1014 | --------------------------------------------------------------------------------