From 51c75d4e30bd990e0c23302366de26f8d6224b84 Mon Sep 17 00:00:00 2001 From: ghe Date: Wed, 10 Jun 2020 12:25:31 +0100 Subject: [PATCH] feat: introduce yarn workspaces scanning test & monitor --- src/cli/args.ts | 1 + .../formatters/format-monitor-response.ts | 3 - src/cli/commands/monitor/index.ts | 2 +- src/cli/index.ts | 6 + src/lib/options-validator.ts | 2 +- src/lib/plugins/get-deps-from-plugin.ts | 25 +- .../nodejs-plugin/yarn-workspaces-parser.ts | 136 +++++ src/lib/reachable-vulns.ts | 1 + src/lib/snyk-test/index.js | 9 +- src/lib/snyk-test/run-test.ts | 4 +- src/lib/types.ts | 3 + test/acceptance/cli-args.test.ts | 1 + .../cli-test/cli-test.yarn-workspaces.spec.ts | 93 ++++ .../workspaces/yarn-workspaces/package.json | 19 + .../packages/apples/package.json | 20 + .../packages/tomatoes/package.json | 10 + .../workspaces/yarn-workspaces/yarn.lock | 501 ++++++++++++++++++ 17 files changed, 820 insertions(+), 16 deletions(-) create mode 100644 src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts create mode 100644 test/acceptance/cli-test/cli-test.yarn-workspaces.spec.ts create mode 100644 test/acceptance/workspaces/yarn-workspaces/package.json create mode 100644 test/acceptance/workspaces/yarn-workspaces/packages/apples/package.json create mode 100644 test/acceptance/workspaces/yarn-workspaces/packages/tomatoes/package.json create mode 100644 test/acceptance/workspaces/yarn-workspaces/yarn.lock diff --git a/src/cli/args.ts b/src/cli/args.ts index 121bd4fff5c..9bc7d51ae53 100644 --- a/src/cli/args.ts +++ b/src/cli/args.ts @@ -181,6 +181,7 @@ export function args(rawArgv: string[]): Args { 'scan-all-unmanaged', 'fail-on', 'all-projects', + 'yarn-workspaces', 'detection-depth', 'reachable-vulns', ]) { diff --git a/src/cli/commands/monitor/formatters/format-monitor-response.ts b/src/cli/commands/monitor/formatters/format-monitor-response.ts index 78bd6a52b47..aa700598a39 100644 --- a/src/cli/commands/monitor/formatters/format-monitor-response.ts +++ b/src/cli/commands/monitor/formatters/format-monitor-response.ts @@ -22,9 +22,6 @@ export function formatMonitorOutput( : res.path; const strOutput = chalk.bold.white('\nMonitoring ' + humanReadableName + '...\n\n') + - (packageManager === 'yarn' - ? 'A yarn.lock file was detected - continuing as a Yarn project.\n' - : '') + 'Explore this snapshot at ' + res.uri + '\n\n' + diff --git a/src/cli/commands/monitor/index.ts b/src/cli/commands/monitor/index.ts index 723195b89eb..e6795a7b095 100644 --- a/src/cli/commands/monitor/index.ts +++ b/src/cli/commands/monitor/index.ts @@ -120,7 +120,7 @@ async function monitor(...args0: MethodArgs): Promise { validateMonitorPath(path, options.docker); let analysisType = 'all'; let packageManager; - if (options.allProjects) { + if (options.allProjects || options.yarnWorkspaces) { analysisType = 'all'; } else if (options.docker) { analysisType = 'docker'; diff --git a/src/cli/index.ts b/src/cli/index.ts index f7de0ebaaf4..79a800949a4 100755 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -244,6 +244,12 @@ async function main() { if (args.options.file && args.options.allProjects) { throw new UnsupportedOptionCombinationError(['file', 'all-projects']); } + if (args.options.yarnWorkspaces && args.options.allProjects) { + throw new UnsupportedOptionCombinationError([ + 'yarn-workspaces', + 'all-projects', + ]); + } if (args.options.packageManager && args.options.allProjects) { throw new UnsupportedOptionCombinationError([ 'package-manager', diff --git a/src/lib/options-validator.ts b/src/lib/options-validator.ts index b71067e0619..7abd5f9f352 100644 --- a/src/lib/options-validator.ts +++ b/src/lib/options-validator.ts @@ -9,7 +9,7 @@ export async function validateOptions( ): Promise { if (options.reachableVulns) { // Throwing error only in case when both packageManager and allProjects not defined - if (!packageManager && !options.allProjects) { + if (!packageManager && !options.allProjects && !options.yarnWorkspaces) { throw new Error('Could not determine package manager'); } const org = options.org || config.org; diff --git a/src/lib/plugins/get-deps-from-plugin.ts b/src/lib/plugins/get-deps-from-plugin.ts index d6419475c11..807907a5ed8 100644 --- a/src/lib/plugins/get-deps-from-plugin.ts +++ b/src/lib/plugins/get-deps-from-plugin.ts @@ -13,9 +13,21 @@ import { import analytics = require('../analytics'); import { convertSingleResultToMultiCustom } from './convert-single-splugin-res-to-multi-custom'; import { convertMultiResultToMultiCustom } from './convert-multi-plugin-res-to-multi-custom'; +import { processYarnWorkspaces } from './nodejs-plugin/yarn-workspaces-parser'; const debug = debugModule('snyk-test'); +const multiProjectProcessors = { + yarnWorkspaces: { + handler: processYarnWorkspaces, + files: ['package.json'], + }, + allProjects: { + handler: getMultiPluginResult, + files: AUTO_DETECTABLE_FILES, + }, +}; + // Force getDepsFromPlugin to return scannedProjects for processing export async function getDepsFromPlugin( root: string, @@ -23,13 +35,14 @@ export async function getDepsFromPlugin( ): Promise { let inspectRes: pluginApi.InspectResult; - if (options.allProjects) { + if (Object.keys(multiProjectProcessors).some((key) => options[key])) { + const scanType = options.yarnWorkspaces ? 'yarnWorkspaces' : 'allProjects'; const levelsDeep = options.detectionDepth; const ignore = options.exclude ? options.exclude.split(',') : []; const targetFiles = await find( root, ignore, - AUTO_DETECTABLE_FILES, + multiProjectProcessors[scanType].files, levelsDeep, ); debug( @@ -39,7 +52,11 @@ export async function getDepsFromPlugin( if (targetFiles.length === 0) { throw NoSupportedManifestsFoundError([root]); } - inspectRes = await getMultiPluginResult(root, options, targetFiles); + inspectRes = await multiProjectProcessors[scanType].handler( + root, + options, + targetFiles, + ); const analyticData = { scannedProjects: inspectRes.scannedProjects.length, targetFiles, @@ -49,7 +66,7 @@ export async function getDepsFromPlugin( levelsDeep, ignore, }; - analytics.add('allProjects', analyticData); + analytics.add(scanType, analyticData); return inspectRes; } diff --git a/src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts b/src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts new file mode 100644 index 00000000000..5ca47e3d9a2 --- /dev/null +++ b/src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts @@ -0,0 +1,136 @@ +import * as baseDebug from 'debug'; +const debug = baseDebug('yarn-workspaces'); +import * as fs from 'fs'; +import * as lockFileParser from 'snyk-nodejs-lockfile-parser'; +import * as path from 'path'; +import { NoSupportedManifestsFoundError } from '../../errors'; +import { + MultiProjectResultCustom, + ScannedProjectCustom, +} from '../get-multi-plugin-result'; + +export async function processYarnWorkspaces( + root: string, + settings: { + strictOutOfSync?: boolean; + scanDevDependencies?: boolean; + }, + targetFiles: string[], +): Promise { + const yarnTargetFiles = targetFiles.filter((f) => f.endsWith('package.json')); + debug(`processing Yarn workspaces (${targetFiles.length})`); + if (yarnTargetFiles.length === 0) { + throw NoSupportedManifestsFoundError([root]); + } + let yarnWorkspacesMap = {}; + const yarnWorkspacesFilesMap = {}; + let isYarnWorkspacePackage = false; + const result: MultiProjectResultCustom = { + plugin: { + name: 'snyk-nodejs-yarn-workspaces', + runtime: process.version, + }, + scannedProjects: [], + }; + for (const packageJsonFileName of yarnTargetFiles) { + const packageJson = getFileContents(root, packageJsonFileName); + yarnWorkspacesMap = { + ...yarnWorkspacesMap, + ...getWorkspacesMap(packageJson), + }; + + for (const workspaceRoot of Object.keys(yarnWorkspacesMap)) { + const workspaces = yarnWorkspacesMap[workspaceRoot].workspaces || []; + const match = workspaces + .map((pattern) => + packageJsonFileName.includes(pattern.replace(/\*/, '')), + ) + .filter(Boolean); + + if (match) { + yarnWorkspacesFilesMap[packageJsonFileName] = { + root: workspaceRoot, + }; + isYarnWorkspacePackage = true; + } + } + + if (isYarnWorkspacePackage) { + const rootDir = path.dirname( + yarnWorkspacesFilesMap[packageJsonFileName].root, + ); + const rootYarnLockfileName = path.join(rootDir, 'yarn.lock'); + + const yarnLock = await getFileContents(root, rootYarnLockfileName); + const res = await lockFileParser.buildDepTree( + packageJson.content, + yarnLock.content, + settings.scanDevDependencies, + lockFileParser.LockfileType.yarn, + settings.strictOutOfSync !== false, + ); + const project: ScannedProjectCustom = { + packageManager: 'yarn', + targetFile: path.parse(packageJson.name).base, + depTree: res as any, + plugin: { + name: 'snyk-nodejs-lockfile-parser', + runtime: process.version, + }, + }; + result.scannedProjects.push(project); + } + } + return result; +} + +function getFileContents( + root: string, + fileName: string, +): { + content: string; + name: string; +} { + const fullPath = path.resolve(root, fileName); + if (!fs.existsSync(fullPath)) { + throw new Error( + 'Manifest ' + fileName + ' not found at location: ' + fileName, + ); + } + const content = fs.readFileSync(fullPath, 'utf-8'); + return { + content, + name: fileName, + }; +} + +interface YarnWorkspacesMap { + [packageJsonName: string]: { + workspaces: string[]; + }; +} + +export function getWorkspacesMap(file: { + content: string; + name: string; +}): YarnWorkspacesMap { + const yarnWorkspacesMap = {}; + if (!file) { + return yarnWorkspacesMap; + } + + try { + const rootFileWorkspacesDefinitions = lockFileParser.getYarnWorkspaces( + file.content, + ); + + if (rootFileWorkspacesDefinitions && rootFileWorkspacesDefinitions.length) { + yarnWorkspacesMap[file.name] = { + workspaces: rootFileWorkspacesDefinitions, + }; + } + } catch (e) { + debug('Failed to process a workspace', e.message); + } + return yarnWorkspacesMap; +} diff --git a/src/lib/reachable-vulns.ts b/src/lib/reachable-vulns.ts index 37c02aa24cc..8c734b96837 100644 --- a/src/lib/reachable-vulns.ts +++ b/src/lib/reachable-vulns.ts @@ -37,6 +37,7 @@ export async function validatePayload( if ( packageManager && !options.allProjects && + !options.yarnWorkspaces && !REACHABLE_VULNS_SUPPORTED_PACKAGE_MANAGERS.includes(packageManager) ) { throw new FeatureNotSupportedByPackageManagerError( diff --git a/src/lib/snyk-test/index.js b/src/lib/snyk-test/index.js index b0b52971616..a6393daf88c 100644 --- a/src/lib/snyk-test/index.js +++ b/src/lib/snyk-test/index.js @@ -32,11 +32,9 @@ async function test(root, options, callback) { function executeTest(root, options) { try { if (!options.allProjects) { - if (options.iac) { - options.packageManager = detect.isIacProject(root, options); - } else { - options.packageManager = detect.detectPackageManager(root, options); - } + options.packageManager = options.iac + ? detect.isIacProject(root, options) + : detect.detectPackageManager(root, options); } return run(root, options).then((results) => { for (const res of results) { @@ -70,6 +68,7 @@ function run(root, options) { !( options.docker || options.allProjects || + options.yarnWorkspaces || pm.SUPPORTED_PACKAGE_MANAGER_NAME[packageManager] ) ) { diff --git a/src/lib/snyk-test/run-test.ts b/src/lib/snyk-test/run-test.ts index cea2a91f1dc..aa814c5da05 100644 --- a/src/lib/snyk-test/run-test.ts +++ b/src/lib/snyk-test/run-test.ts @@ -190,10 +190,10 @@ async function parseRes( pkgManager, options.severityThreshold, ); - // For Node.js: inject additional information (for remediation etc.) into the response. if (payload.modules) { - res.dependencyCount = payload.modules.numDependencies; + res.dependencyCount = + payload.modules.numDependencies || depGraph.getPkgs().length - 1; if (res.vulnerabilities) { res.vulnerabilities.forEach((vuln) => { if (payload.modules && payload.modules.pluck) { diff --git a/src/lib/types.ts b/src/lib/types.ts index 902f2b700b4..8c01fd956ec 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -19,6 +19,7 @@ export interface TestOptions { showVulnPaths: ShowVulnPaths; failOn?: FailOn; reachableVulns?: boolean; + yarnWorkspaces?: boolean; } export interface WizardOptions { @@ -63,6 +64,7 @@ export interface Options { allProjects?: boolean; detectionDepth?: number; exclude?: string; + strictOutOfSync?: boolean; // Used with the Docker plugin only. Allows requesting some experimental/unofficial features. experimental?: boolean; } @@ -85,6 +87,7 @@ export interface MonitorOptions { // Used with the Docker plugin only. Allows requesting some experimental/unofficial features. experimental?: boolean; reachableVulns?: boolean; + yarnWorkspaces?: boolean; } export interface MonitorMeta { diff --git a/test/acceptance/cli-args.test.ts b/test/acceptance/cli-args.test.ts index 7ed01400152..f637226d83d 100644 --- a/test/acceptance/cli-args.test.ts +++ b/test/acceptance/cli-args.test.ts @@ -120,6 +120,7 @@ const argsNotAllowedWithAllProjects = [ 'project-name', 'docker', 'all-sub-projects', + 'yarn-workspaces', ]; argsNotAllowedWithAllProjects.forEach((arg) => { diff --git a/test/acceptance/cli-test/cli-test.yarn-workspaces.spec.ts b/test/acceptance/cli-test/cli-test.yarn-workspaces.spec.ts new file mode 100644 index 00000000000..81a4e5982b1 --- /dev/null +++ b/test/acceptance/cli-test/cli-test.yarn-workspaces.spec.ts @@ -0,0 +1,93 @@ +import { AcceptanceTests } from './cli-test.acceptance.test'; + +export const YarnTests: AcceptanceTests = { + language: 'Yarn', + tests: { + // yarn lockfile based testing is only supported for node 4+ + '`test yarn-workspaces-out-of-sync --yarn-workspaces` out of sync fails': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + try { + await params.cli.test('yarn-out-of-sync', { dev: true }); + t.fail('Should fail'); + } catch (e) { + t.equal( + e.message, + '\nTesting yarn-out-of-sync...\n\n' + + 'Dependency snyk was not found in yarn.lock.' + + ' Your package.json and yarn.lock are probably out of sync.' + + ' Please run "yarn install" and try again.', + 'Contains enough info about err', + ); + } + }, + '`test yarn-workspaces-workspace-out-of-sync --yarn-workspaces --strict-out-of-sync=false` passes': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + await params.cli.test('yarn-workspaces-out-of-sync', { + dev: true, + strictOutOfSync: false, + }); + const req = params.server.popRequest(); + t.match(req.url, '/test-dep-graph', 'posts to correct url'); + const depGraph = req.body.depGraph; + t.same( + depGraph.pkgs.map((p) => p.id).sort(), + [ + // TODO: add packages + ].sort(), + 'depGraph looks fine', + ); + }, + + '`test yarn-workspace --yarn-workspaces --dev` sends pkg info': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + await params.cli.test('yarn-workspace', { + yanrWorkspaces: true, + dev: true, + }); + const req = params.server.popRequest(); + t.match(req.url, '/test-dep-graph', 'posts to correct url'); + t.match(req.body.targetFile, undefined, 'target is undefined'); + const depGraph = req.body.depGraph; + t.same( + depGraph.pkgs.map((p) => p.id).sort(), + [ + // TODO: add packages + ].sort(), + 'depGraph looks fine', + ); + }, + '`test` on a yarn workspace does work and displays appropriate text': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces('yarn-workspace'); + await params.cli.test(); + const req = params.server.popRequest(); + t.equal(req.method, 'POST', 'makes POST request'); + t.equal( + req.headers['x-snyk-cli-version'], + params.versionNumber, + 'sends version number', + ); + t.match(req.url, '/test-dep-graph', 'posts to correct url'); + t.match(req.body.targetFile, undefined, 'target is undefined'); + const depGraph = req.body.depGraph; + t.same( + depGraph.pkgs.map((p) => p.id).sort(), + [ + // TODO: add packages + ].sort(), + 'depGraph looks fine', + ); + }, + }, +}; diff --git a/test/acceptance/workspaces/yarn-workspaces/package.json b/test/acceptance/workspaces/yarn-workspaces/package.json new file mode 100644 index 00000000000..a5e8eac850c --- /dev/null +++ b/test/acceptance/workspaces/yarn-workspaces/package.json @@ -0,0 +1,19 @@ +{ + "private": true, + "workspaces": [ + "packages/*" + ], + "resolutions": { + "node-fetch": "^2.3.0" + }, + "engines": { + "node": "^8.11.1 || ^10.11.0", + "yarn": "1.10.1" + }, + "devDependencies": { + "wsrun": "^3.6.2" + }, + "dependencies": { + "node-fetch": "^2.3.0" + } +} diff --git a/test/acceptance/workspaces/yarn-workspaces/packages/apples/package.json b/test/acceptance/workspaces/yarn-workspaces/packages/apples/package.json new file mode 100644 index 00000000000..0c517e52e05 --- /dev/null +++ b/test/acceptance/workspaces/yarn-workspaces/packages/apples/package.json @@ -0,0 +1,20 @@ +{ + "name": "apples", + "version": "1.0.0", + "license": "UNLICENSED", + "main": "./src/index.js", + "scripts": { + "precommit": "lint-staged" + }, + "jest": { + "preset": "@lego-shop/lego-scripts" + }, + "babel": { + "presets": [ + "@lego-shop/lego-scripts/babel" + ] + }, + "dependencies": { + "debug": "^2.7.2" + } +} diff --git a/test/acceptance/workspaces/yarn-workspaces/packages/tomatoes/package.json b/test/acceptance/workspaces/yarn-workspaces/packages/tomatoes/package.json new file mode 100644 index 00000000000..a5dddde28eb --- /dev/null +++ b/test/acceptance/workspaces/yarn-workspaces/packages/tomatoes/package.json @@ -0,0 +1,10 @@ +{ + "name": "tomatoes", + "version": "1.0.0", + "license": "UNLICENSED", + "main": "./src/index.js", + "dependencies": { + "object-assign": "4.1.1", + "node-fetch": "2.2.0" + } +} diff --git a/test/acceptance/workspaces/yarn-workspaces/yarn.lock b/test/acceptance/workspaces/yarn-workspaces/yarn.lock new file mode 100644 index 00000000000..9111d3f0e77 --- /dev/null +++ b/test/acceptance/workspaces/yarn-workspaces/yarn.lock @@ -0,0 +1,501 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +bluebird@^3.5.1: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + +chalk@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +debug@^2.7.2: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + 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" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +glob@^7.1.2: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.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" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash@^4.17.4: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= + dependencies: + mimic-fn "^1.0.0" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +node-fetch@2.2.0, node-fetch@^2.3.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" + integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + +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" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +object-assign@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + 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" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + 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" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +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" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + 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" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +signal-exit@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +split@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== + dependencies: + through "2" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + 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.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +throat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" + integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= + +through@2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +wsrun@^3.6.2: + version "3.6.6" + resolved "https://registry.yarnpkg.com/wsrun/-/wsrun-3.6.6.tgz#b4a9235f175fb4a8e0e3747fc0e09d093fa84d9c" + integrity sha512-XGSx5bNjdLNUF8wMg6R3FZ5H07Rj46DW7LU6fCuf75V75STIm6vyb/f1wXVc5wK8BSHBDqmrZAzxMgOegI3Opw== + dependencies: + bluebird "^3.5.1" + chalk "^2.3.0" + glob "^7.1.2" + lodash "^4.17.4" + minimatch "^3.0.4" + split "^1.0.1" + throat "^4.1.0" + yargs "^10.0.3" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yargs-parser@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== + dependencies: + camelcase "^4.1.0" + +yargs@^10.0.3: + version "10.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== + 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"