From 2a050b0297a6fd25ca11eb193c79d0c914b821a0 Mon Sep 17 00:00:00 2001 From: Ian Sutherland Date: Tue, 19 Dec 2017 14:06:00 -0700 Subject: [PATCH 01/34] fix(cli): handle no devDependencies when listing production dependencies (#5100) (#5109) **Summary** Fixes a bug when running `yarn list --production` and no devDependencies exist. Fixes #5100 **Test plan** * Create a package with no devDependencies and run `yarn list --production`. No error should be thrown. --- __tests__/commands/list.js | 10 ++++++++++ .../fixtures/list/no-dev-deps-production/a/index.js | 1 + .../list/no-dev-deps-production/a/package.json | 4 ++++ .../fixtures/list/no-dev-deps-production/package.json | 5 +++++ .../fixtures/list/no-dev-deps-production/yarn.lock | 6 ++++++ src/cli/commands/list.js | 6 +++++- 6 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 __tests__/fixtures/list/no-dev-deps-production/a/index.js create mode 100644 __tests__/fixtures/list/no-dev-deps-production/a/package.json create mode 100644 __tests__/fixtures/list/no-dev-deps-production/package.json create mode 100644 __tests__/fixtures/list/no-dev-deps-production/yarn.lock diff --git a/__tests__/commands/list.js b/__tests__/commands/list.js index b134d40652..37ca00e629 100644 --- a/__tests__/commands/list.js +++ b/__tests__/commands/list.js @@ -171,6 +171,16 @@ describe('list', () => { }); }); + test('does not error listing dependencies when production and no devDependencies exist', async (): Promise => { + let thrown = false; + try { + await runList([], {production: true}, 'no-dev-deps-production'); + } catch (e) { + thrown = true; + } + expect(thrown).toEqual(false); + }); + test('getParent should extract a parent object from a hash, if the parent key exists', () => { const mockTreesByKey = {}; diff --git a/__tests__/fixtures/list/no-dev-deps-production/a/index.js b/__tests__/fixtures/list/no-dev-deps-production/a/index.js new file mode 100644 index 0000000000..5e8802b488 --- /dev/null +++ b/__tests__/fixtures/list/no-dev-deps-production/a/index.js @@ -0,0 +1 @@ +left-pad; diff --git a/__tests__/fixtures/list/no-dev-deps-production/a/package.json b/__tests__/fixtures/list/no-dev-deps-production/a/package.json new file mode 100644 index 0000000000..9113c2528e --- /dev/null +++ b/__tests__/fixtures/list/no-dev-deps-production/a/package.json @@ -0,0 +1,4 @@ +{ + "name": "a", + "version": "1.0.0" +} diff --git a/__tests__/fixtures/list/no-dev-deps-production/package.json b/__tests__/fixtures/list/no-dev-deps-production/package.json new file mode 100644 index 0000000000..10f20a42d8 --- /dev/null +++ b/__tests__/fixtures/list/no-dev-deps-production/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "a": "file:./a" + } +} diff --git a/__tests__/fixtures/list/no-dev-deps-production/yarn.lock b/__tests__/fixtures/list/no-dev-deps-production/yarn.lock new file mode 100644 index 0000000000..f8564acbc3 --- /dev/null +++ b/__tests__/fixtures/list/no-dev-deps-production/yarn.lock @@ -0,0 +1,6 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"a@file:./a": + version "1.0.0" diff --git a/src/cli/commands/list.js b/src/cli/commands/list.js index 8952f21dab..f0dff3ea04 100644 --- a/src/cli/commands/list.js +++ b/src/cli/commands/list.js @@ -184,7 +184,11 @@ export function filterTree(tree: Tree, filters: Array, pattern: string = } export function getDevDeps(manifest: Object): Set { - return new Set(Object.keys(manifest.devDependencies).map(key => `${key}@${manifest.devDependencies[key]}`)); + if (manifest.devDependencies) { + return new Set(Object.keys(manifest.devDependencies).map(key => `${key}@${manifest.devDependencies[key]}`)); + } else { + return new Set(); + } } export async function run(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { From 51513f0b5c054edc354614d8fbd7855ce5b36e09 Mon Sep 17 00:00:00 2001 From: Soo Jae Hwang Date: Wed, 20 Dec 2017 06:26:07 +0900 Subject: [PATCH 02/34] fix(output): "yarn licenses list" hide progress bar before displaying tree (#5103) fixes #5098 **Summary** The progress bar is now removed before displaying a tree through the `ConsoleReporter`. --- src/reporters/console/console-reporter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/reporters/console/console-reporter.js b/src/reporters/console/console-reporter.js index a1e047c602..48e7208f0f 100644 --- a/src/reporters/console/console-reporter.js +++ b/src/reporters/console/console-reporter.js @@ -230,6 +230,7 @@ export default class ConsoleReporter extends BaseReporter { } // handles basic tree output to console tree(key: string, trees: Trees) { + this.stopProgress(); // const output = ({name, children, hint, color}, titlePrefix, childrenPrefix) => { const formatter = this.format; From 63598f401923209c38f9654a93169b0bccb43f24 Mon Sep 17 00:00:00 2001 From: Ian Sutherland Date: Tue, 26 Dec 2017 18:54:37 -0700 Subject: [PATCH 03/34] fix(cli): allow GitHub project names that contain the string .git (#5117) (#5119) fixes #5117 * fix(cli): allow GitHub project names that contain the string .git (#5117) * Fixed regex for matching .git --- __tests__/resolvers/exotics/hosted-git-resolver.js | 12 ++++++++++++ src/resolvers/exotics/hosted-git-resolver.js | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/__tests__/resolvers/exotics/hosted-git-resolver.js b/__tests__/resolvers/exotics/hosted-git-resolver.js index 74b57e1117..cbd225394c 100644 --- a/__tests__/resolvers/exotics/hosted-git-resolver.js +++ b/__tests__/resolvers/exotics/hosted-git-resolver.js @@ -42,3 +42,15 @@ test('explodeHostedGitFragment should work identical with and without .git suffi expect(explodeHostedGitFragment(fragmentWithoutGit, reporter)).toEqual(expectedFragment); expect(explodeHostedGitFragment(fragmentWithGit, reporter)).toEqual(expectedFragment); }); + +test('explodeHostedGitFragment should allow the project name to contain .git', () => { + const fragmentString = 'jure/lens.github'; + + const expectedFragment: ExplodedFragment = { + user: 'jure', + repo: 'lens.github', + hash: '', + }; + + expect(explodeHostedGitFragment(fragmentString, reporter)).toEqual(expectedFragment); +}); diff --git a/src/resolvers/exotics/hosted-git-resolver.js b/src/resolvers/exotics/hosted-git-resolver.js index 49bc1a436e..d4b68d0c87 100644 --- a/src/resolvers/exotics/hosted-git-resolver.js +++ b/src/resolvers/exotics/hosted-git-resolver.js @@ -55,7 +55,7 @@ export function explodeHostedGitFragment(fragment: string, reporter: Reporter): if (repoParts.length <= 3) { return { user, - repo: repoParts[0].replace('.git', ''), + repo: repoParts[0].replace(/\.git$/, ''), hash: repoParts[1] || '', }; } From a2a054438fe91f9860dd06cc4ee7b8004ad7efa0 Mon Sep 17 00:00:00 2001 From: Yunyu Lin Date: Mon, 1 Jan 2018 15:30:42 -0700 Subject: [PATCH 04/34] feat(cli): add script-shell config setting for NPM compatibility (#5133) fixes 4248 **Summary** * feat(cli): allow running scripts with custom shell (#4248) * Limit custom shell to yarn run **Test plan** * Add expected args test for execCommand with custom script-shell --- __tests__/commands/run.js | 24 +++++++++++++++++- .../fixtures/run/script-shell/package.json | 6 +++++ src/cli/commands/run.js | 7 +++++- src/util/execute-lifecycle-script.js | 25 ++++++++++++++++--- 4 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 __tests__/fixtures/run/script-shell/package.json diff --git a/__tests__/commands/run.js b/__tests__/commands/run.js index 6f692c4231..2f4a238249 100644 --- a/__tests__/commands/run.js +++ b/__tests__/commands/run.js @@ -37,6 +37,18 @@ const runRunInWorkspacePackage = function(cwd, ...args): Promise { return retVal; })(...args); }; +const runRunWithCustomShell = function(customShell, ...args): Promise { + return buildRun.bind(null, BufferReporter, fixturesLoc, (args, flags, config, reporter): Promise => { + const yarnRegistry = config.registries.yarn; + const originalCustomShell = yarnRegistry.config['script-shell']; + yarnRegistry.config['script-shell'] = customShell; + const retVal = run(config, reporter, flags, args); + retVal.then(() => { + yarnRegistry.config['script-shell'] = originalCustomShell; + }); + return retVal; + })(...args); +}; test('lists all available commands with no arguments', (): Promise => { return runRun([], {}, 'no-args', (config, reporter): ?Promise => { @@ -63,7 +75,7 @@ test('lists all available commands with no arguments', (): Promise => { test('runs script containing spaces', (): Promise => { return runRun(['build'], {}, 'spaces', async (config): ?Promise => { const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); - // The command get's called with a space appended + // The command gets called with a space appended const args = ['build', config, pkg.scripts.build, config.cwd]; expect(execCommand).toBeCalledWith(...args); @@ -167,3 +179,13 @@ test('adds workspace root node_modules/.bin to path when in a workspace', (): Pr expect(envPaths).toContain(path.join(config.cwd, 'packages', 'pkg1', 'node_modules', '.bin')); }); }); + +test('runs script with custom script-shell', (): Promise => { + return runRunWithCustomShell('/usr/bin/dummy', ['start'], {}, 'script-shell', async (config): ?Promise => { + const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); + // The command gets called with the provided customShell + const args = ['start', config, pkg.scripts.start, config.cwd, '/usr/bin/dummy']; + + expect(execCommand).toBeCalledWith(...args); + }); +}); diff --git a/__tests__/fixtures/run/script-shell/package.json b/__tests__/fixtures/run/script-shell/package.json new file mode 100644 index 0000000000..7adbf000a9 --- /dev/null +++ b/__tests__/fixtures/run/script-shell/package.json @@ -0,0 +1,6 @@ +{ + "license": "MIT", + "scripts": { + "start": "echo $SHELL" + } +} diff --git a/src/cli/commands/run.js b/src/cli/commands/run.js index b512e6d3f7..300acf89f2 100644 --- a/src/cli/commands/run.js +++ b/src/cli/commands/run.js @@ -81,7 +81,12 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg for (const [stage, cmd] of cmds) { // only tack on trailing arguments for default script, ignore for pre and post - #1595 const cmdWithArgs = stage === action ? sh`${unquoted(cmd)} ${args}` : cmd; - await execCommand(stage, config, cmdWithArgs, config.cwd); + const customShell = config.getOption('script-shell'); + if (customShell) { + await execCommand(stage, config, cmdWithArgs, config.cwd, String(customShell)); + } else { + await execCommand(stage, config, cmdWithArgs, config.cwd); + } } } else if (action === 'env') { reporter.log(JSON.stringify(await makeEnv('env', config.cwd, config), null, 2), {force: true}); diff --git a/src/util/execute-lifecycle-script.js b/src/util/execute-lifecycle-script.js index b89d002355..7dde2629cc 100644 --- a/src/util/execute-lifecycle-script.js +++ b/src/util/execute-lifecycle-script.js @@ -171,6 +171,7 @@ export async function executeLifecycleScript( cwd: string, cmd: string, spinner?: ReporterSpinner, + customShell?: string, ): LifecycleReturn { // if we don't have a spinner then pipe everything to the terminal const stdio = spinner ? undefined : 'inherit'; @@ -180,7 +181,17 @@ export async function executeLifecycleScript( await checkForGypIfNeeded(config, cmd, env[constants.ENV_PATH_KEY].split(path.delimiter)); // get shell - if (process.platform === 'win32') { + let sh = 'sh'; + let shFlag = '-c'; + + let windowsVerbatimArguments = undefined; + + if (customShell) { + sh = customShell; + } else if (process.platform === 'win32') { + sh = process.env.comspec || 'cmd'; + shFlag = '/d /s /c'; + windowsVerbatimArguments = true; // handle windows run scripts starting with a relative path cmd = fixCmdWinSlashes(cmd); } @@ -204,7 +215,7 @@ export async function executeLifecycleScript( } }; } - const stdout = await child.spawn(cmd, [], {shell: true, cwd, env, stdio}, updateProgress); + const stdout = await child.spawn(sh, [shFlag, cmd], {cwd, env, stdio, windowsVerbatimArguments}, updateProgress); return {cwd, command: cmd, stdout}; } @@ -260,11 +271,17 @@ export async function execFromManifest(config: Config, commandName: string, cwd: } } -export async function execCommand(stage: string, config: Config, cmd: string, cwd: string): Promise { +export async function execCommand( + stage: string, + config: Config, + cmd: string, + cwd: string, + customShell?: string, +): Promise { const {reporter} = config; try { reporter.command(cmd); - await executeLifecycleScript(stage, config, cwd, cmd); + await executeLifecycleScript(stage, config, cwd, cmd, undefined, customShell); return Promise.resolve(); } catch (err) { if (err instanceof ProcessTermError) { From 3e1c3a7ed27e017dcbe7c2a189de37fd705ff97f Mon Sep 17 00:00:00 2001 From: Ian Sutherland Date: Tue, 2 Jan 2018 07:14:07 -0700 Subject: [PATCH 05/34] fix(resolution): support semver: in git URLs (#5126) (#5140) fixes #5126 **Summary** * Add support for github URLs that include `semver:^x.x.x` in the tag/branch name. This is supported by NPM so improves compatibility. --- __tests__/util/git/git-ref-resolver.js | 17 +++++++++++++++++ src/util/git/git-ref-resolver.js | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/__tests__/util/git/git-ref-resolver.js b/__tests__/util/git/git-ref-resolver.js index de6fc4e74e..01d540a25c 100644 --- a/__tests__/util/git/git-ref-resolver.js +++ b/__tests__/util/git/git-ref-resolver.js @@ -22,6 +22,7 @@ test('resolveVersion', async () => { const refs: GitRefs = new Map(); refs.set('refs/heads/1.1', 'eaa56cb34863810060abbec2d755ba51508afedc'); refs.set('refs/heads/3.3', '4cff93aa6e8270c3bec988af464d28a164bc3cb2'); + refs.set('refs/heads/v3.3.0', '06910374874035a3388c42a6f6403b2b785e9993'); refs.set('refs/heads/main', '8a41a314e23dc566a6b7e73c757a10d13e3320cf'); refs.set('refs/heads/both', '106c28537be070b98ca1effaef6a2bf6414e1e49'); refs.set('refs/tags/v1.1.0', '37d5ed001dc4402d5446911c4e1cb589449e7d8d'); @@ -110,6 +111,22 @@ test('resolveVersion', async () => { sha: '8a41a314e23dc566a6b7e73c757a10d13e3320cf', ref: 'refs/heads/main', }); + expect(await resolve('^1.0')).toEqual({ + sha: '37d5ed001dc4402d5446911c4e1cb589449e7d8d', + ref: 'refs/tags/v1.1.0', + }); + expect(await resolve('semver:^1.0')).toEqual({ + sha: '37d5ed001dc4402d5446911c4e1cb589449e7d8d', + ref: 'refs/tags/v1.1.0', + }); + expect(await resolve('^3.0')).toEqual({ + sha: '06910374874035a3388c42a6f6403b2b785e9993', + ref: 'refs/heads/v3.3.0', + }); + expect(await resolve('semver:^3.0')).toEqual({ + sha: '06910374874035a3388c42a6f6403b2b785e9993', + ref: 'refs/heads/v3.3.0', + }); }); test('isCommitSha', () => { diff --git a/src/util/git/git-ref-resolver.js b/src/util/git/git-ref-resolver.js index 2c011f2f32..532f9eb555 100644 --- a/src/util/git/git-ref-resolver.js +++ b/src/util/git/git-ref-resolver.js @@ -94,7 +94,7 @@ const tryVersionAsTagSemver = async ( {version, config, refs}: ResolveVersionOptions, names: Names, ): Promise => { - const result = await findSemver(version, config, names.tags); + const result = await findSemver(version.replace(/^semver:/, ''), config, names.tags); return result ? tryRef(refs, `${REF_TAG_PREFIX}${result}`) : null; }; @@ -102,7 +102,7 @@ const tryVersionAsBranchSemver = async ( {version, config, refs}: ResolveVersionOptions, names: Names, ): Promise => { - const result = await findSemver(version, config, names.heads); + const result = await findSemver(version.replace(/^semver:/, ''), config, names.heads); return result ? tryRef(refs, `${REF_BRANCH_PREFIX}${result}`) : null; }; From 35a186e4f36a9344823a1041f6745c93b36c1fb5 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Mon, 8 Jan 2018 18:47:45 +0100 Subject: [PATCH 06/34] chore(deps): restore semver ranges (#5175) --- package.json | 4 ++-- yarn.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 6ae2454032..832d6ceebf 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "dnscache": "^1.0.1", "eslint-plugin-jest": "^20.0.3", "eslint-plugin-jsx-a11y": "^6.0.2", - "eslint-plugin-relay": "0.0.8", + "eslint-plugin-relay": "^0.0.8", "glob": "^7.1.1", "gunzip-maybe": "^1.4.0", "ini": "^1.3.4", @@ -82,7 +82,7 @@ "gulp-sourcemaps": "^2.2.0", "gulp-util": "^3.0.7", "gulp-watch": "^4.3.5", - "jest": "21.2.1", + "jest": "^21.2.1", "jsinspect": "^0.12.6", "minimatch": "^3.0.4", "mock-stdin": "^0.3.0", diff --git a/yarn.lock b/yarn.lock index e74ecdb1c6..04d62360d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1963,7 +1963,7 @@ eslint-plugin-react@^7.1.0: has "^1.0.1" jsx-ast-utils "^1.4.1" -eslint-plugin-relay@0.0.8: +eslint-plugin-relay@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/eslint-plugin-relay/-/eslint-plugin-relay-0.0.8.tgz#68d99f9fdc518a146bb8aee7519538aa56528dc8" dependencies: @@ -3471,7 +3471,7 @@ jest-validate@^21.2.1: leven "^2.1.0" pretty-format "^21.2.1" -jest@21.2.1: +jest@^21.2.1: version "21.2.1" resolved "https://registry.yarnpkg.com/jest/-/jest-21.2.1.tgz#c964e0b47383768a1438e3ccf3c3d470327604e1" dependencies: From 8be4eef75414db89875f5c64b71cf06783b4507a Mon Sep 17 00:00:00 2001 From: Bartosz Kaszubowski Date: Mon, 8 Jan 2018 19:44:24 +0100 Subject: [PATCH 07/34] test(package-resolver): fix hash and no ".git" extension tests (#5165) Summary OCaml repos has been moved so URLs had to be updated. I have also extended timeout from 60 s to 90 s because 2 out of 9 test runs failed with default value on my machine while fetching OCaml. By tweaking this value I have achieved 100% success rate. --- __tests__/package-resolver.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/__tests__/package-resolver.js b/__tests__/package-resolver.js index 5e8f2b9100..68136a5117 100644 --- a/__tests__/package-resolver.js +++ b/__tests__/package-resolver.js @@ -9,7 +9,7 @@ import makeTemp from './_temp.js'; import * as fs from '../src/util/fs.js'; import * as constants from '../src/constants.js'; -jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000; +jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000; const path = require('path'); @@ -51,10 +51,9 @@ function addTest(pattern, registry = 'npm', init: ?(cacheFolder: string) => Prom }); } -// TODO Got broken for some time, needs revision -// addTest('https://github.com/npm-ml/re'); // git url with no .git -// addTest('git+https://github.com/npm-ml/ocaml.git#npm-4.02.3'); // git+hash -// addTest('https://github.com/npm-ml/ocaml.git#npm-4.02.3'); // hash +addTest('https://github.com/ocaml/ocaml-re'); // git url with no .git +addTest('git+https://github.com/ocaml/ocaml.git#4.02.3'); // git+hash +addTest('https://github.com/ocaml/ocaml.git#4.02.3'); // hash addTest('https://git@github.com/stevemao/left-pad.git'); // git url, with username addTest('https://bitbucket.org/hgarcia/node-bitbucket-api.git'); // hosted git url addTest('https://github.com/yarnpkg/yarn/releases/download/v0.18.1/yarn-v0.18.1.tar.gz'); // tarball From bf23687088f1053bb55c6b0587edfb0cdd73f6ae Mon Sep 17 00:00:00 2001 From: Ian Sutherland Date: Mon, 8 Jan 2018 13:55:39 -0700 Subject: [PATCH 08/34] fix(cli): check if workspaces setting in package.json is an array (#5089) (#5114) Summary Display a helpful error message if workspaces in package.json is not an array. Currently just displays: error An unexpected error occurred: "patterns.map is not a function". Fixes #5089 Test plan Create a package.json file with workspaces: "packages/*" Run yarn and observe that this error message is shown: The workspaces setting in package.json must be an array. --- src/config.js | 3 +++ src/reporters/lang/en.js | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/config.js b/src/config.js index 21300ac5e8..d59ad58b68 100644 --- a/src/config.js +++ b/src/config.js @@ -640,6 +640,9 @@ export default class Config { if (!rootManifest.private && patterns.length > 0) { throw new MessageError(this.reporter.lang('workspacesRequirePrivateProjects')); } + if (!Array.isArray(patterns)) { + throw new MessageError(this.reporter.lang('workspacesSettingMustBeArray')); + } const registryFilenames = registryNames .map(registryName => this.registries[registryName].constructor.filename) diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index ac12f341b5..c2fcf1dbbb 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -181,7 +181,8 @@ const messages = { workspacesAddRootCheck: 'Running this command will add the dependency to the workspace root rather than workspace itself, which might not be what you want - if you really meant it, make it explicit by running this command again with the -W flag (or --ignore-workspace-root-check).', - workspacesRequirePrivateProjects: 'Workspaces can only be enabled in private projects', + workspacesRequirePrivateProjects: 'Workspaces can only be enabled in private projects.', + workspacesSettingMustBeArray: 'The workspaces field in package.json must be an array.', workspacesDisabled: 'Your project root defines workspaces but the feature is disabled in your Yarn config. Please check "workspaces-experimental" in your .yarnrc file.', workspaceRootNotFound: "Cannot find the root of your workspace - are you sure you're currently in a workspace?", From fb6511c96057d999420a0c4b4e5e6efbe3f99932 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" Date: Mon, 8 Jan 2018 14:15:56 -0800 Subject: [PATCH 09/34] Configure Renovate (#5178) * Add renovate.json * :preserveSemverRanges --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000000..5fcce11213 --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "extends": [ + "config:base", + ":preserveSemverRanges" + ] +} From edb45a0919e6fa72b203462fc494ee279e8e6198 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" Date: Mon, 15 Jan 2018 11:26:51 +0000 Subject: [PATCH 10/34] fix(deps): update dependency is-builtin-module to ^2.0.0 (#5186) --- package.json | 2 +- yarn.lock | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 832d6ceebf..0836a2192d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "ini": "^1.3.4", "inquirer": "^3.0.1", "invariant": "^2.2.0", - "is-builtin-module": "^1.0.0", + "is-builtin-module": "^2.0.0", "is-ci": "^1.0.10", "is-webpack-bundle": "^1.0.0", "leven": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index 04d62360d6..76e5e39bbd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1245,6 +1245,10 @@ builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" +builtin-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -3001,6 +3005,12 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" +is-builtin-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-2.0.0.tgz#431104b3b4ba838ec7a17d82bb3bccd2233e8cd9" + dependencies: + builtin-modules "^2.0.0" + is-callable@^1.1.1, is-callable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" From c13ce58c4efbef391a97274c295a1e1ab68a317e Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Mon, 15 Jan 2018 11:27:41 +0000 Subject: [PATCH 11/34] Add comma to yesWarning text (#5177) Remove ambiguity in the warning message, to clarify that answering "yes" to all questions may have security implications, not that all questions which may have security implications will be answered with "yes". --- src/reporters/lang/en.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index c2fcf1dbbb..eb606d4835 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -98,7 +98,7 @@ const messages = { ignoredScripts: 'Ignored scripts due to flag.', missingAddDependencies: 'Missing list of packages to add to your project.', yesWarning: - 'The yes flag has been set. This will automatically answer yes to all questions which may have security implications.', + 'The yes flag has been set. This will automatically answer yes to all questions, which may have security implications.', networkWarning: "You don't appear to have an internet connection. Try the --offline flag to use the cache for registry queries.", flatGlobalError: From 2153794abdb5d8bd75185b5d6f4044d0c6d9b85d Mon Sep 17 00:00:00 2001 From: Robert Martin Date: Mon, 15 Jan 2018 06:28:36 -0500 Subject: [PATCH 12/34] Update en.js (#5153) A few minor edits for style/grammar --- src/reporters/lang/en.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index eb606d4835..573cedc277 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -118,14 +118,14 @@ const messages = { frozenLockfileError: 'Your lockfile needs to be updated, but yarn was run with `--frozen-lockfile`.', fileWriteError: 'Could not write file $0: $1', multiplePackagesCantUnpackInSameDestination: - 'Pattern $0 is trying to unpack in the same destination $1 as pattern $2. This could result in a non deterministic behavior, skipping.', + 'Pattern $0 is trying to unpack in the same destination $1 as pattern $2. This could result in non-deterministic behavior, skipping.', incorrectLockfileEntry: 'Lockfile has incorrect entry for $0. Ignoring it.', invalidResolutionName: 'Resolution field $0 does not end with a valid package name and will be ignored', invalidResolutionVersion: 'Resolution field $0 has an invalid version entry and may be ignored', incompatibleResolutionVersion: 'Resolution field $0 is incompatible with requested version $1', - yarnOutdated: "Your current version of Yarn is out of date. The latest version is $0 while you're on $1.", + yarnOutdated: "Your current version of Yarn is out of date. The latest version is $0, while you're on $1.", yarnOutdatedInstaller: 'To upgrade, download the latest installer at $0.', yarnOutdatedCommand: 'To upgrade, run the following command:', From e0dfd420b17a0d7ee69dad9a5e5ea87b743db47d Mon Sep 17 00:00:00 2001 From: Konstantin Raev Date: Mon, 15 Jan 2018 05:27:08 -0800 Subject: [PATCH 13/34] Speed up global list command (#5148) * Speed up global list command * extracted only necessary code for list comand * lint fixes * Update install.js * Update global.js --- __tests__/commands/add.js | 2 -- src/cli/commands/global.js | 4 ++-- src/cli/commands/install.js | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/__tests__/commands/add.js b/__tests__/commands/add.js index da2d2277f8..308f7729c3 100644 --- a/__tests__/commands/add.js +++ b/__tests__/commands/add.js @@ -1,7 +1,5 @@ /* @flow */ -import type {Prompt} from 'inquirer'; - import {ConsoleReporter} from '../../src/reporters/index.js'; import * as reporters from '../../src/reporters/index.js'; import { diff --git a/src/cli/commands/global.js b/src/cli/commands/global.js index ccc5a83abe..3ecc91fad1 100644 --- a/src/cli/commands/global.js +++ b/src/cli/commands/global.js @@ -199,8 +199,8 @@ async function list(config: Config, reporter: Reporter, flags: Object, args: Arr // install so we get hard file paths const lockfile = await Lockfile.fromDirectory(config.cwd); - const install = new Install({skipIntegrityCheck: true}, config, new NoopReporter(), lockfile); - const patterns = await install.init(); + const install = new Install({}, config, new NoopReporter(), lockfile); + const patterns = await install.getFlattenedDeps(); // dump global modules for (const pattern of patterns) { diff --git a/src/cli/commands/install.js b/src/cli/commands/install.js index e8003f6e35..a8a0f6c58a 100644 --- a/src/cli/commands/install.js +++ b/src/cli/commands/install.js @@ -473,6 +473,21 @@ export class Install { } } + /** + * helper method that gets only recent manifests + * used by global.ls command + */ + async getFlattenedDeps(): Promise> { + const {requests: depRequests, patterns: rawPatterns} = await this.fetchRequestFromCwd(); + + await this.resolver.init(depRequests, {}); + + const manifests = await fetcher.fetch(this.resolver.getManifests(), this.config); + this.resolver.updateManifests(manifests); + + return this.flatten(rawPatterns); + } + /** * TODO description */ From 3ac83340b8863c9988a3c37afc79cf3a37fcc4ed Mon Sep 17 00:00:00 2001 From: Georg Vienna Date: Mon, 15 Jan 2018 14:27:56 +0100 Subject: [PATCH 14/34] fix(cli): Run version script hook AFTER bumping the package version, but BEFORE commit. (#5151) --- src/cli/commands/version.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/commands/version.js b/src/cli/commands/version.js index c75ae40b07..ca7bfd9024 100644 --- a/src/cli/commands/version.js +++ b/src/cli/commands/version.js @@ -116,6 +116,8 @@ export async function setVersion( } await config.saveRootManifests(manifests); + await runLifecycle('version'); + // check if committing the new version to git is overriden if (!flags.gitTagVersion || !config.getOption('version-git-tag')) { // Don't tag the version in Git @@ -137,8 +139,6 @@ export async function setVersion( } } - await runLifecycle('version'); - if (isGit) { const message = (flags.message || String(config.getOption('version-git-message'))).replace(/%s/g, newVersion); const sign: boolean = Boolean(config.getOption('version-sign-git-tag')); From eaa9be87e0a086603dc598bf9fa86480a9d1690a Mon Sep 17 00:00:00 2001 From: Ian Sutherland Date: Mon, 15 Jan 2018 06:31:14 -0700 Subject: [PATCH 15/34] feat(cli): improve error message when file resolver can't find file (#5134) (#5145) * feat(cli): improve error message when file resolver can't find file (#5134) * Update en.js * Update en.js --- src/reporters/lang/en.js | 2 +- src/resolvers/exotics/file-resolver.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index 573cedc277..13f0416ce6 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -80,7 +80,7 @@ const messages = { invalidVersion: 'Invalid version supplied.', requiredVersionInRange: 'Required version in range.', packageNotFoundRegistry: "Couldn't find package $0 on the $1 registry.", - doesntExist: "$0 doesn't exist.", + doesntExist: "Package $1 refers to a non-existing file '$0'.", missingRequiredPackageKey: `Package $0 doesn't have a $1.`, invalidAccess: 'Invalid argument for access, expected public or restricted.', invalidCommand: 'Invalid subcommand. Try $0', diff --git a/src/resolvers/exotics/file-resolver.js b/src/resolvers/exotics/file-resolver.js index 1ee891336c..cea7c18dc9 100644 --- a/src/resolvers/exotics/file-resolver.js +++ b/src/resolvers/exotics/file-resolver.js @@ -49,7 +49,7 @@ export default class FileResolver extends ExoticResolver { return manifest; } if (!await fs.exists(loc)) { - throw new MessageError(this.reporter.lang('doesntExist', loc)); + throw new MessageError(this.reporter.lang('doesntExist', loc, this.pattern.split('@')[0])); } const manifest: Manifest = await (async () => { From b2ce74e4697bbe84c6d40396cfbb828044b03435 Mon Sep 17 00:00:00 2001 From: Ian Sutherland Date: Mon, 15 Jan 2018 06:35:31 -0700 Subject: [PATCH 16/34] feat(cli): group by license in licenses list (#5074) (#5110) --- .../commands/__snapshots__/licenses.js.snap | 2 +- src/cli/commands/licenses.js | 77 +++++++++++++------ 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/__tests__/commands/__snapshots__/licenses.js.snap b/__tests__/commands/__snapshots__/licenses.js.snap index 594ed7e2e8..f8b7ffdf8f 100644 --- a/__tests__/commands/__snapshots__/licenses.js.snap +++ b/__tests__/commands/__snapshots__/licenses.js.snap @@ -3,7 +3,7 @@ exports[`lists all licenses of the dependencies with the --json argument 1`] = ` "{\\"type\\":\\"warning\\",\\"data\\":\\"package.json: No license field\\"} {\\"type\\":\\"warning\\",\\"data\\":\\"No license field\\"} -{\\"type\\":\\"tree\\",\\"data\\":{\\"type\\":\\"licenses\\",\\"trees\\":[{\\"name\\":\\"is-plain-obj@1.1.0\\",\\"children\\":[{\\"name\\":\\"License: MIT\\"},{\\"name\\":\\"URL: https://github.com/sindresorhus/is-plain-obj.git\\"}]}]}} +{\\"type\\":\\"tree\\",\\"data\\":{\\"type\\":\\"licenses\\",\\"trees\\":[{\\"name\\":\\"MIT\\",\\"children\\":[{\\"name\\":\\"is-plain-obj@1.1.0\\",\\"children\\":[{\\"name\\":\\"URL: https://github.com/sindresorhus/is-plain-obj.git\\"},{\\"name\\":\\"VendorUrl: sindresorhus.com\\"},{\\"name\\":\\"VendorName: Sindre Sorhus\\"}]}]}]}} " `; diff --git a/src/cli/commands/licenses.js b/src/cli/commands/licenses.js index 1d95c73bf7..da680ae634 100644 --- a/src/cli/commands/licenses.js +++ b/src/cli/commands/licenses.js @@ -49,44 +49,71 @@ async function getManifests(config: Config, flags: Object): Promise): Promise { const manifests: Array = await getManifests(config, flags); + const manifestsByLicense = new Map(); + + for (const {name, version, license, repository, homepage, author} of manifests) { + const licenseKey = license || 'UNKNOWN'; + const url = repository ? repository.url : homepage; + const vendorUrl = homepage || (author && author.url); + const vendorName = author && author.name; + + if (!manifestsByLicense.has(licenseKey)) { + manifestsByLicense.set(licenseKey, new Map()); + } + + const byLicense = manifestsByLicense.get(licenseKey); + invariant(byLicense, 'expected value'); + byLicense.set(`${name}@${version}`, { + name, + version, + url, + vendorUrl, + vendorName, + }); + } if (flags.json) { const body = []; - for (const {name, version, license, repository, homepage, author} of manifests) { - const url = repository ? repository.url : homepage; - const vendorUrl = homepage || (author && author.url); - const vendorName = author && author.name; - body.push([ - name, - version, - license || 'Unknown', - url || 'Unknown', - vendorUrl || 'Unknown', - vendorName || 'Unknown', - ]); - } + manifestsByLicense.forEach((license, licenseKey) => { + license.forEach(({name, version, url, vendorUrl, vendorName}) => { + body.push([name, version, licenseKey, url || 'Unknown', vendorUrl || 'Unknown', vendorName || 'Unknown']); + }); + }); reporter.table(['Name', 'Version', 'License', 'URL', 'VendorUrl', 'VendorName'], body); } else { const trees = []; - for (const {name, version, license, repository, homepage} of manifests) { - const children = []; - children.push({ - name: `${reporter.format.bold('License:')} ${license || reporter.format.red('UNKNOWN')}`, - }); + manifestsByLicense.forEach((license, licenseKey) => { + const licenseTree = []; - const url = repository ? repository.url : homepage; - if (url) { - children.push({name: `${reporter.format.bold('URL:')} ${url}`}); - } + license.forEach(({name, version, url, vendorUrl, vendorName}) => { + const children = []; + + if (url) { + children.push({name: `${reporter.format.bold('URL:')} ${url}`}); + } + + if (vendorUrl) { + children.push({name: `${reporter.format.bold('VendorUrl:')} ${vendorUrl}`}); + } + + if (vendorName) { + children.push({name: `${reporter.format.bold('VendorName:')} ${vendorName}`}); + } + + licenseTree.push({ + name: `${name}@${version}`, + children, + }); + }); trees.push({ - name: `${name}@${version}`, - children, + name: licenseKey, + children: licenseTree, }); - } + }); reporter.tree('licenses', trees); } From 05b4e011a793d488df982c7cae6aed603ea057c0 Mon Sep 17 00:00:00 2001 From: Ian Sutherland Date: Mon, 15 Jan 2018 06:37:22 -0700 Subject: [PATCH 17/34] feat(cli): include notice with license when generating disclaimer (#5072) (#5111) --- src/cli/commands/licenses.js | 21 ++++++++++++++------- src/types.js | 1 + src/util/normalize-manifest/fix.js | 13 +++++++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/cli/commands/licenses.js b/src/cli/commands/licenses.js index da680ae634..61c9fa00e6 100644 --- a/src/cli/commands/licenses.js +++ b/src/cli/commands/licenses.js @@ -148,16 +148,23 @@ export const {run, examples} = buildSubCommands('licenses', { // the same license text are grouped together. const manifestsByLicense: Map> = new Map(); for (const manifest of manifests) { - const {licenseText} = manifest; + const {licenseText, noticeText} = manifest; + let licenseKey; if (!licenseText) { continue; } - if (!manifestsByLicense.has(licenseText)) { - manifestsByLicense.set(licenseText, new Map()); + if (!noticeText) { + licenseKey = licenseText; + } else { + licenseKey = `${licenseText}\n\nNOTICE\n\n${noticeText}`; + } + + if (!manifestsByLicense.has(licenseKey)) { + manifestsByLicense.set(licenseKey, new Map()); } - const byLicense = manifestsByLicense.get(licenseText); + const byLicense = manifestsByLicense.get(licenseKey); invariant(byLicense, 'expected value'); byLicense.set(manifest.name, manifest); } @@ -168,7 +175,7 @@ export const {run, examples} = buildSubCommands('licenses', { ); console.log(); - for (const [licenseText, manifests] of manifestsByLicense) { + for (const [licenseKey, manifests] of manifestsByLicense) { console.log('-----'); console.log(); @@ -191,8 +198,8 @@ export const {run, examples} = buildSubCommands('licenses', { console.log(heading.join(' ')); console.log(); - if (licenseText) { - console.log(licenseText.trim()); + if (licenseKey) { + console.log(licenseKey.trim()); } else { // what do we do here? base it on `license`? } diff --git a/src/types.js b/src/types.js index 63b3a459e2..1f5a800617 100644 --- a/src/types.js +++ b/src/types.js @@ -68,6 +68,7 @@ export type Manifest = { flat?: boolean, license?: string, licenseText?: string, + noticeText?: string, readme?: string, readmeFilename?: string, diff --git a/src/util/normalize-manifest/fix.js b/src/util/normalize-manifest/fix.js index 8ce398e6b6..53845efead 100644 --- a/src/util/normalize-manifest/fix.js +++ b/src/util/normalize-manifest/fix.js @@ -308,6 +308,19 @@ export default (async function( } } + // get notice file + const noticeFile = files.find((filename): boolean => { + const lower = filename.toLowerCase(); + return lower === 'notice' || lower.startsWith('notice.'); + }); + if (noticeFile) { + const noticeFilepath = path.join(moduleLoc, noticeFile); + const noticeFileStats = await fs.stat(noticeFilepath); + if (noticeFileStats.isFile()) { + info.noticeText = await fs.readFile(noticeFilepath); + } + } + for (const dependencyType of MANIFEST_FIELDS) { const dependencyList = info[dependencyType]; if (dependencyList && typeof dependencyList === 'object') { From 1c3a2de8e245617bb50f4c4fcd1b63a807e2c29c Mon Sep 17 00:00:00 2001 From: Ian Sutherland Date: Mon, 15 Jan 2018 06:40:00 -0700 Subject: [PATCH 18/34] fix(cli): improve guessing of package names that contain a dot (#5102) (#5135) --- __tests__/util/guess-name.js | 15 +++++++++++++++ src/util/guess-name.js | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/__tests__/util/guess-name.js b/__tests__/util/guess-name.js index a9115480a1..f7fc41be6d 100644 --- a/__tests__/util/guess-name.js +++ b/__tests__/util/guess-name.js @@ -24,6 +24,13 @@ const examples = [ 'awesome-name.tar.gz', ]; +const dotExamples = [ + 'awesomename/awesome.name', + 'awesomename/awesome.name.git', + 'awesomename/awesome.name.tar.gz', + 'awesomename/awesome.name.tar.bz2', +]; + describe('guessName', () => { for (const source of examples) { it(`guess name of ${source}`, () => { @@ -31,3 +38,11 @@ describe('guessName', () => { }); } }); + +describe('guessName dot examples', () => { + for (const source of dotExamples) { + it(`guess name of ${source}`, () => { + expect(guessName(source)).toBe('awesome.name'); + }); + } +}); diff --git a/src/util/guess-name.js b/src/util/guess-name.js index a922718412..88352c89df 100644 --- a/src/util/guess-name.js +++ b/src/util/guess-name.js @@ -4,7 +4,7 @@ import url from 'url'; function cleanup(name: string): string { name = name.replace(/-\d+\.\d+\.\d+/, ''); - return name.split('.')[0]; + return name.replace(/\.git$|\.zip$|\.tar\.gz$|\.tar\.bz2$/, ''); } function guessNameFallback(source: string): string { From 6adbd472129b5410436ddefbd92093868bd98e49 Mon Sep 17 00:00:00 2001 From: Jeff Valore Date: Mon, 15 Jan 2018 08:45:08 -0500 Subject: [PATCH 19/34] fix(resolution) Eliminate "missing peerDep" warning when dep exists at root level. (#5088) * test(resolution): Added a (failing) unit test to reproduce issue #4743 Added a failing unit test to reproduce issue #4743. It seems that if a peerDep exists deeper in the dep tree than where it is included, yarn will output a earning, even if that peerDep is satisfied by the same library included shallower in the tree, or at the root level. * fix(resolution): No longer warn for mising peerDep when it exists at multiple levels. A missing peerDep warning was being issued if the exact same pattern was a deep transitive dep and a direct dep. This was due to only the first request for a pattern being added to the list of requests that peerDep was checking. Now all references are tracked. Also fixed a logic error in Warn where a dep would be reported multiple times. #4743 * fix(tests): Remove snapshot test of "yarn why" due to different output local vs ci. Now assert with Remove snapshot test of "yarn why" due to different output local vs ci. Now assert with actual object value comparison. --- __tests__/commands/install/integration.js | 19 ++++++++++ __tests__/commands/why.js | 15 ++++++++ .../b/package.json | 11 ++++++ .../package.json | 9 +++++ .../GET/registry.yarnpkg.com/browserslist.bin | 21 +++++++++++ .../-/browserslist-2.10.0.tgz.bin | Bin 0 -> 14855 bytes .../GET/registry.yarnpkg.com/caniuse-api.bin | 21 +++++++++++ .../caniuse-api/-/caniuse-api-2.0.0.tgz.bin | Bin 0 -> 4959 bytes .../GET/registry.yarnpkg.com/caniuse-lite.bin | 21 +++++++++++ .../-/caniuse-lite-1.0.30000782.tgz.bin | Bin 0 -> 236874 bytes .../electron-to-chromium.bin | 21 +++++++++++ .../-/electron-to-chromium-1.3.28.tgz.bin | Bin 0 -> 4479 bytes .../GET/registry.yarnpkg.com/loader-utils.bin | Bin 5610 -> 10392 bytes .../registry.yarnpkg.com/lodash.memoize.bin | 21 +++++++++++ .../dep-included-at-2-levels/b/package.json | 8 +++++ .../why/dep-included-at-2-levels/package.json | 9 +++++ src/cli/commands/why.js | 4 +-- src/package-request.js | 4 ++- src/package-resolver.js | 33 ++++++++++-------- src/reporters/buffer-reporter.js | 2 +- 20 files changed, 200 insertions(+), 19 deletions(-) create mode 100644 __tests__/fixtures/install/peer-dep-included-at-2-levels/b/package.json create mode 100644 __tests__/fixtures/install/peer-dep-included-at-2-levels/package.json create mode 100644 __tests__/fixtures/request-cache/GET/registry.yarnpkg.com/browserslist.bin create mode 100644 __tests__/fixtures/request-cache/GET/registry.yarnpkg.com/browserslist/-/browserslist-2.10.0.tgz.bin create mode 100644 __tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-api.bin create mode 100644 __tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-api/-/caniuse-api-2.0.0.tgz.bin create mode 100644 __tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-lite.bin create mode 100644 __tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000782.tgz.bin create mode 100644 __tests__/fixtures/request-cache/GET/registry.yarnpkg.com/electron-to-chromium.bin create mode 100644 __tests__/fixtures/request-cache/GET/registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.28.tgz.bin create mode 100644 __tests__/fixtures/request-cache/GET/registry.yarnpkg.com/lodash.memoize.bin create mode 100644 __tests__/fixtures/why/dep-included-at-2-levels/b/package.json create mode 100644 __tests__/fixtures/why/dep-included-at-2-levels/package.json diff --git a/__tests__/commands/install/integration.js b/__tests__/commands/install/integration.js index e12ff5b0f6..b606e04a9e 100644 --- a/__tests__/commands/install/integration.js +++ b/__tests__/commands/install/integration.js @@ -1177,3 +1177,22 @@ test.concurrent('install will not overwrite linked dependencies', async (): Prom }); }); }); + +// There was a warning being generated when a peerDep existed at a deeper level, and at the top level. +// See https://github.com/yarnpkg/yarn/issues/4743 +// +// package.json +// |- b +// | |- caniuse-api +// | |- caniuse-lite +// |- caniuse-lite +// +// When `b` also has a peerDep on `caniuse-lite` then Yarn was issuing a warning that the dep was missing. +test.concurrent('install will not warn for missing peerDep when both shallower and deeper', (): Promise => { + return runInstall({}, 'peer-dep-included-at-2-levels', (config, reporter, install, getStdout) => { + const stdout = getStdout(); + const messageParts = reporter.lang('unmetPeer').split('undefined'); + const warningMessage = messageParts.every(part => stdout.includes(part)); + expect(warningMessage).toBe(false); + }); +}); diff --git a/__tests__/commands/why.js b/__tests__/commands/why.js index e1464d4178..0580a5b889 100644 --- a/__tests__/commands/why.js +++ b/__tests__/commands/why.js @@ -106,3 +106,18 @@ test.concurrent('should determine that the module installed because it is hoiste expect(report[report.length - 2].data).toEqual(reporter.lang('whyHoistedTo', 'glob#minimatch')); }); }); + +test('should report when a module is included multiple times including the root', (): Promise => { + return runWhy({}, ['caniuse-lite'], 'dep-included-at-2-levels', (config, reporter) => { + const report = reporter.getBuffer(); + const reasons = report + .filter(entry => entry.type === 'list' && entry.data.type === 'reasons') + .map(entry => entry.data.items)[0]; + + expect(reasons).toEqual([ + '"b#caniuse-api" depends on it', + '"b#caniuse-api#browserslist" depends on it', + 'Specified in "dependencies"', + ]); + }); +}); diff --git a/__tests__/fixtures/install/peer-dep-included-at-2-levels/b/package.json b/__tests__/fixtures/install/peer-dep-included-at-2-levels/b/package.json new file mode 100644 index 0000000000..c8773ac8fa --- /dev/null +++ b/__tests__/fixtures/install/peer-dep-included-at-2-levels/b/package.json @@ -0,0 +1,11 @@ +{ + "name": "b", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "caniuse-api": "^2.0.0" + }, + "peerDependencies": { + "caniuse-lite": "^1.0.30000697" + } +} diff --git a/__tests__/fixtures/install/peer-dep-included-at-2-levels/package.json b/__tests__/fixtures/install/peer-dep-included-at-2-levels/package.json new file mode 100644 index 0000000000..190b600fc8 --- /dev/null +++ b/__tests__/fixtures/install/peer-dep-included-at-2-levels/package.json @@ -0,0 +1,9 @@ +{ + "name": "a", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "b": "file:./b", + "caniuse-lite": "^1.0.0" + } +} diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/browserslist.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/browserslist.bin new file mode 100644 index 0000000000..7b1c57a4f9 --- /dev/null +++ b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/browserslist.bin @@ -0,0 +1,21 @@ +HTTP/1.1 200 OK +Date: Mon, 11 Dec 2017 18:38:51 GMT +Content-Type: application/vnd.npm.install-v1+json +Content-Length: 35115 +Connection: keep-alive +Set-Cookie: __cfduid=d88832e1949be97719a1f327c4bc4f7421513017531; expires=Tue, 11-Dec-18 18:38:51 GMT; path=/; domain=.yarnpkg.com; HttpOnly +Cache-Control: max-age=300 +Last-Modified: Wed, 6 Dec 2017 18:43:00 GMT +ETag: "5a283a34-892b" +Accept-Ranges: bytes +Via: 1.1 varnish +Age: 4519 +X-Served-By: cache-mdw17347-MDW +X-Cache: HIT +X-Cache-Hits: 1 +X-Timer: S1513017532.709306,VS0,VE0 +Vary: Accept-Encoding, Accept +Server: cloudflare-nginx +CF-RAY: 3cba90352e7f5625-ORD + +{"versions":{"0.1.0":{"name":"browserslist","version":"0.1.0","dependencies":{"caniuse-db":"^1.0.30000032 "},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.0.1","chai":"1.10.0","gulp":"3.8.10"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b566254ca06832bd3326f1559a2361fed92bd691","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.1.0.tgz"}},"0.1.1":{"name":"browserslist","version":"0.1.1","dependencies":{"caniuse-db":"^1.0.30000043"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"1.10.0","gulp":"3.8.10"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"279e955e6e00afcfc4dcc6160d79aea44db0645c","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.1.1.tgz"}},"0.1.2":{"name":"browserslist","version":"0.1.2","dependencies":{"caniuse-db":"^1.0.30000048"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"1.10.0","gulp":"3.8.10"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e27e20730dd426149bab8051073a41fc9d3cf238","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.1.2.tgz"}},"0.1.3":{"name":"browserslist","version":"0.1.3","dependencies":{"caniuse-db":"^1.0.30000054"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"1.10.0","gulp":"3.8.10"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2f67975c24bb357b6b48b4bc46e7c39a1f0b3b5b","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.1.3.tgz"}},"0.2.0":{"name":"browserslist","version":"0.2.0","dependencies":{"caniuse-db":"^1.0.30000054"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.0","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"1.10.0","gulp":"3.8.10"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e5b7cf311cccb70772cd22d4f61c7bb80523ecd2","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.2.0.tgz"}},"0.3.0":{"name":"browserslist","version":"0.3.0","dependencies":{"caniuse-db":"^1.0.30000078"},"devDependencies":{"jshint-stylish":"1.0.0","gulp-jshint":"1.9.2","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"2.0.0","gulp":"3.8.11"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"f4429e509b25e00c43d77bb60cc0be37292613f6","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.3.0.tgz"}},"0.3.1":{"name":"browserslist","version":"0.3.1","dependencies":{"caniuse-db":"^1.0.30000081"},"devDependencies":{"jshint-stylish":"1.0.1","gulp-jshint":"1.9.2","gulp-mocha":"2.0.0","mocha":"2.1.0","chai":"2.1.0","gulp":"3.8.11"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"d60dd16f4aa10087f18b4b19d6432f9f79bdc833","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.3.1.tgz"}},"0.3.2":{"name":"browserslist","version":"0.3.2","dependencies":{"caniuse-db":"^1.0.30000113"},"devDependencies":{"gulp-eslint":"0.6.0","gulp-mocha":"2.0.1","mocha":"2.2.1","chai":"2.2.0","gulp":"3.8.11"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"4e516ed1882086ff2479bab80cd164b3ae463545","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.3.2.tgz"}},"0.3.3":{"name":"browserslist","version":"0.3.3","dependencies":{"caniuse-db":"^1.0.30000127"},"devDependencies":{"gulp-eslint":"0.9.0","gulp-mocha":"2.0.1","mocha":"2.2.4","chai":"2.2.0","gulp":"3.8.11"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"c21beb6b3d3c2492404084781113f39fc133f2c0","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.3.3.tgz"}},"0.4.0":{"name":"browserslist","version":"0.4.0","dependencies":{"caniuse-db":"^1.0.30000153"},"devDependencies":{"gulp-eslint":"0.11.1","gulp-mocha":"2.0.1","mocha":"2.2.4","chai":"2.3.0","gulp":"3.8.11"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"3bd4ab9199dc1b9150d4d6dba4d9d3aabbc86dd4","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.4.0.tgz"}},"0.5.0":{"name":"browserslist","version":"0.5.0","dependencies":{"caniuse-db":"^1.0.30000214"},"devDependencies":{"gulp-eslint":"0.14.0","gulp-mocha":"2.1.2","mocha":"2.2.5","chai":"3.0.0","gulp":"3.9.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b82882493637c342b66ad3182c919e1dac6d1724","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-0.5.0.tgz"}},"1.0.0":{"name":"browserslist","version":"1.0.0","dependencies":{"caniuse-db":"^1.0.30000281"},"devDependencies":{"gulp-eslint":"1.0.0","gulp-mocha":"2.1.3","mocha":"2.3.0","chai":"3.2.0","gulp":"3.9.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"678336f890f2b5bd3cdf2093150533dcbab3e185","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.0.0.tgz"}},"1.0.1":{"name":"browserslist","version":"1.0.1","dependencies":{"caniuse-db":"^1.0.30000335"},"devDependencies":{"gulp-eslint":"1.0.0","gulp-mocha":"2.1.3","mocha":"2.3.3","chai":"3.3.0","gulp":"3.9.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"ef0dd708318cdf74325faeea59efec84d9464717","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.0.1.tgz"}},"1.1.0":{"name":"browserslist","version":"1.1.0","dependencies":{"caniuse-db":"^1.0.30000384"},"devDependencies":{"eslint":"1.10.3","ava":"0.9.1"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"a9ef42c2a51b51becefb3ce525ebee908a578bc5","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.1.0.tgz"}},"1.1.1":{"name":"browserslist","version":"1.1.1","dependencies":{"caniuse-db":"^1.0.30000387"},"devDependencies":{"eslint":"1.10.3","ava":"0.9.1"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"a333af8331160e1db14219ec1cc9b2da20cd4d37","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.1.1.tgz"}},"1.1.2":{"name":"browserslist","version":"1.1.2","dependencies":{"caniuse-db":"^1.0.30000409"},"devDependencies":{"eslint-config-postcss":"^1.0.0","eslint":"1.10.3","ava":"0.11.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"ee71ae31fc87764da23816fc4f09d2346a31879b","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.1.2.tgz"}},"1.1.3":{"name":"browserslist","version":"1.1.3","dependencies":{"caniuse-db":"^1.0.30000409"},"devDependencies":{"eslint-config-postcss":"1.0.0","eslint":"1.10.3","ava":"0.11.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"63e0f1fd68545a56eccafca55b7b722918ebfff5","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.1.3.tgz"}},"1.2.0":{"name":"browserslist","version":"1.2.0","dependencies":{"caniuse-db":"^1.0.30000430"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.4.0","ava":"0.13.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"ef1b039b4cdd75f43382fa13a24f2a8d5da536d0","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.2.0.tgz"}},"1.3.0":{"name":"browserslist","version":"1.3.0","dependencies":{"caniuse-db":"^1.0.30000431"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.4.0","ava":"0.13.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"517bca7192a3b47fd1d71a92366bb2b30b50eed2","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.3.0.tgz"}},"1.3.1":{"name":"browserslist","version":"1.3.1","dependencies":{"caniuse-db":"^1.0.30000444"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.6.0","ava":"0.13.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"6198006485d3a350732408dca74165b69abfa718","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.3.1.tgz"}},"1.3.2":{"name":"browserslist","version":"1.3.2","dependencies":{"caniuse-db":"^1.0.30000471"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.11.1","ava":"0.15.1"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"afb4309174edae938d3042ab0f55dcc2fd88806a","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.3.2.tgz"}},"1.3.3":{"name":"browserslist","version":"1.3.3","dependencies":{"caniuse-db":"^1.0.30000484"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.13.0","ava":"0.15.2"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2fc1e896ed3636e2649651f74907b53254ddad6a","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.3.3.tgz"}},"1.3.4":{"name":"browserslist","version":"1.3.4","dependencies":{"caniuse-db":"^1.0.30000488"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"2.13.1","ava":"0.15.2"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"97bba1a98f011f976333a053706d089ffc9b30fa","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.3.4.tgz"}},"1.3.5":{"name":"browserslist","version":"1.3.5","dependencies":{"caniuse-db":"^1.0.30000506"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"3.0.1","ava":"0.15.2"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2a1daf9b82b654186337ec13de4684b8f78450d7","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.3.5.tgz"}},"1.3.6":{"name":"browserslist","version":"1.3.6","dependencies":{"caniuse-db":"^1.0.30000525"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"3.3.1","ava":"0.16.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"952ff48d56463d3b538f85ef2f8eaddfd284b133","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.3.6.tgz"}},"1.4.0":{"name":"browserslist","version":"1.4.0","dependencies":{"caniuse-db":"^1.0.30000539"},"devDependencies":{"eslint-config-postcss":"2.0.2","eslint":"3.6.0","ava":"0.16.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9cfdcf5384d9158f5b70da2aa00b30e8ff019049","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.4.0.tgz"}},"1.5.0":{"name":"browserslist","version":"1.5.0","dependencies":{"caniuse-db":"^1.0.30000601"},"devDependencies":{"eslint":"^3.11.1","eslint-config-postcss":"^2.0.2","jest":"^18.0.0","lint-staged":"^3.2.2","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b9a1f3880dcc7afdf07baf48c8385200530eb126","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.5.0.tgz"}},"1.5.1":{"name":"browserslist","version":"1.5.1","dependencies":{"caniuse-db":"^1.0.30000601"},"devDependencies":{"eslint":"^3.11.1","eslint-config-postcss":"^2.0.2","jest":"^18.0.0","lint-staged":"^3.2.2","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"67c3f2a1a6ad174cd01d25d2362e6e6083b26986","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.5.1.tgz"}},"1.5.2":{"name":"browserslist","version":"1.5.2","dependencies":{"caniuse-db":"^1.0.30000604"},"devDependencies":{"eslint":"^3.11.1","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.2.5","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1c82fde0ee8693e6d15c49b7bff209dc06298c56","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.5.2.tgz"}},"1.6.0":{"name":"browserslist","version":"1.6.0","dependencies":{"caniuse-db":"^1.0.30000613","electron-to-chromium":"^1.2.0"},"devDependencies":{"eslint":"^3.14.0","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.2.7","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"85fb7c993540d3fda31c282baf7f5aee698ac9ee","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.6.0.tgz"}},"1.7.0":{"name":"browserslist","version":"1.7.0","dependencies":{"caniuse-db":"^1.0.30000617","electron-to-chromium":"^1.2.1"},"devDependencies":{"eslint":"^3.14.1","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.2.8","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"738df5b2971354d198b2fbd5a22c560d2d896084","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.7.0.tgz"}},"1.7.1":{"name":"browserslist","version":"1.7.1","dependencies":{"caniuse-db":"^1.0.30000617","electron-to-chromium":"^1.2.1"},"devDependencies":{"eslint":"^3.14.1","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.2.9","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"cc9bd193979a2a4b09fdb3df6003fefe48ccefe1","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.7.1.tgz"}},"1.7.2":{"name":"browserslist","version":"1.7.2","dependencies":{"caniuse-db":"^1.0.30000622","electron-to-chromium":"^1.2.2"},"devDependencies":{"eslint":"^3.15.0","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.3.0","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"cf4977283c3e692d6dcc241192e9de91504ff331","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.7.2.tgz"}},"1.7.3":{"name":"browserslist","version":"1.7.3","dependencies":{"caniuse-db":"^1.0.30000623","electron-to-chromium":"^1.2.2"},"devDependencies":{"eslint":"^3.15.0","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.3.0","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"25ead9c917b278ad668b83f39c8025697797b2ab","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.7.3.tgz"}},"1.7.4":{"name":"browserslist","version":"1.7.4","dependencies":{"caniuse-db":"^1.0.30000624","electron-to-chromium":"^1.2.2"},"devDependencies":{"eslint":"^3.15.0","eslint-config-postcss":"^2.0.2","jest":"^18.1.0","lint-staged":"^3.3.0","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"56a12da876f787223743a866224ccd8f97014628","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.7.4.tgz"}},"1.7.5":{"name":"browserslist","version":"1.7.5","dependencies":{"caniuse-db":"^1.0.30000624","electron-to-chromium":"^1.2.3"},"devDependencies":{"eslint":"^3.16.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.1","lint-staged":"^3.3.1","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"eca4713897b51e444283241facf3985de49a9e2b","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.7.5.tgz"}},"1.7.6":{"name":"browserslist","version":"1.7.6","dependencies":{"caniuse-db":"^1.0.30000631","electron-to-chromium":"^1.2.5"},"devDependencies":{"eslint":"^3.16.1","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.3.1","pre-commit":"^1.1.3","yaspeller":"^3.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"af98589ce6e7ab09618d29451faacb81220bd3ba","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.7.6.tgz"}},"1.7.7":{"name":"browserslist","version":"1.7.7","dependencies":{"caniuse-db":"^1.0.30000639","electron-to-chromium":"^1.2.7"},"devDependencies":{"eslint":"^3.18.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.0","pre-commit":"^1.1.3","yaspeller-ci":"^0.3.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"0bd76704258be829b2398bb50e4b62d1a166b0b9","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz"}},"2.0.0":{"name":"browserslist","version":"2.0.0","dependencies":{"caniuse-lite":"^1.0.30000657","electron-to-chromium":"^1.3.6"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.0","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"f9251e5c728eb7f18020b6743c2ef03feaff2a27","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.0.0.tgz"}},"2.1.0":{"name":"browserslist","version":"2.1.0","dependencies":{"caniuse-lite":"^1.0.30000659","electron-to-chromium":"^1.3.8"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.0","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2590d3de07c7129a7bd05ce3c3cb2a3fc56e78fa","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.1.0.tgz"}},"2.1.1":{"name":"browserslist","version":"2.1.1","dependencies":{"caniuse-lite":"^1.0.30000664","electron-to-chromium":"^1.3.8"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.1","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"d0da26318d86352be7693d407977b8523cc78b11","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.1.1.tgz"}},"2.1.2":{"name":"browserslist","version":"2.1.2","dependencies":{"caniuse-lite":"^1.0.30000665","electron-to-chromium":"^1.3.9"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^19.0.2","lint-staged":"^3.4.1","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"a9dd0791342dab019861c2dd1cd0fd5d83230d39","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.1.2.tgz"}},"2.1.3":{"name":"browserslist","version":"2.1.3","dependencies":{"caniuse-lite":"^1.0.30000670","electron-to-chromium":"^1.3.11"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^20.0.3","lint-staged":"^3.4.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"302dc8e5e44f3d5937850868aab13e11cac3dbc7","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.1.3.tgz"}},"2.1.4":{"name":"browserslist","version":"2.1.4","dependencies":{"caniuse-lite":"^1.0.30000670","electron-to-chromium":"^1.3.11"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^3.19.0","eslint-config-postcss":"^2.0.2","jest":"^20.0.3","lint-staged":"^3.4.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"cc526af4a1312b7d2e05653e56d0c8ab70c0e053","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.1.4.tgz"}},"2.1.5":{"name":"browserslist","version":"2.1.5","dependencies":{"caniuse-lite":"^1.0.30000684","electron-to-chromium":"^1.3.14"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.0.0","eslint-config-postcss":"^2.0.2","jest":"^20.0.4","lint-staged":"^3.6.1","pre-commit":"^1.1.3","yaspeller-ci":"^0.4.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e882550df3d1cd6d481c1a3e0038f2baf13a4711","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.1.5.tgz"}},"2.2.0":{"name":"browserslist","version":"2.2.0","dependencies":{"caniuse-lite":"^1.0.30000701","electron-to-chromium":"^1.3.15"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.2.0","eslint-config-postcss":"^2.0.2","jest":"^20.0.4","lint-staged":"^4.0.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-t09UuOv/4/hrL1y4wZ871+kKE6E2bkdMD6duZtV7FZIHFpsmdQfW63BH3bAjkfpkbP/eFKyenUbDUKigV/VmRw==","shasum":"5e35ec993e467c6464b8cb708447386891de9f50","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.2.0.tgz"}},"2.2.1":{"name":"browserslist","version":"2.2.1","dependencies":{"caniuse-lite":"^1.0.30000704","electron-to-chromium":"^1.3.16"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.3.0","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-q9NH7wY49FzqqsYHBv2kA/A5XUaaEvWShX3OGLugthdeqnCEaSEmU/TffiIDlcrb5XISYGCNyLvxtnHgOu1qVA==","shasum":"709048c57bf3bf9b382105c396a737ad525d948e","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.2.1.tgz"}},"2.2.2":{"name":"browserslist","version":"2.2.2","dependencies":{"caniuse-lite":"^1.0.30000704","electron-to-chromium":"^1.3.16"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.3.0","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-MejxGMNIeIqzgaMKVYfFTWHinrwZOnWMXteN9VlHinTd13/0aDmXY9uyRqNsCTnVxqRmrjQFcXI7cy0q9K1IYg==","shasum":"e9b4618b8a01c193f9786beea09f6fd10dbe31c3","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.2.2.tgz"}},"2.3.0":{"name":"browserslist","version":"2.3.0","dependencies":{"caniuse-lite":"^1.0.30000710","electron-to-chromium":"^1.3.17"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.3.0","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.2","pre-commit":"^1.1.3","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-jDr9Mea+n+FwI+kR0ce7rXCFBoM7hbL80G/th7oPxuNSK4V5J3LPMHB5vykjeI2h7fgSihBbSdoJPmzUC0606Q==","shasum":"b2aa76415c71643fe2368f6243b43bbbb4211752","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.3.0.tgz"}},"2.3.1":{"name":"browserslist","version":"2.3.1","dependencies":{"caniuse-lite":"^1.0.30000712","electron-to-chromium":"^1.3.17"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.4.1","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.3","pre-commit":"^1.1.3","size-limit":"^0.8.1","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-YSRvpyaxDBBAPkwYO0THouUmA+cvYbyBHZrP/byJEUGDT9r/6TQcDASBtrAj4S45Le6JZbV8oeUAPR9wT8tisg==","shasum":"39500a2090330b2a090120ea6c7fc78b6e091c5e","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.3.1.tgz"}},"2.3.2":{"name":"browserslist","version":"2.3.2","dependencies":{"caniuse-lite":"^1.0.30000715","electron-to-chromium":"^1.3.18"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.4.1","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.3","pre-commit":"^1.1.3","size-limit":"^0.8.4","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-arvLUwBTsmpfmyMfoBQH8WWICiyaVkMxJsft73/rTRU80rAPSXsi3M0uYBcUH22w7MG475eET31F4M0+31w81g==","shasum":"343ff101cce799d5eaf0b742e17d0d21efc2d379","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.3.2.tgz"}},"2.3.3":{"name":"browserslist","version":"2.3.3","dependencies":{"caniuse-lite":"^1.0.30000715","electron-to-chromium":"^1.3.18"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.4.1","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.3","pre-commit":"^1.1.3","size-limit":"^0.9.0","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-p9hz6FA2H1w1ZUAXKfK3MlIA4Z9fEd56hnZSOecBIITb5j0oZk/tZRwhdE0xG56RGx2x8cc1c5AWJKWVjMLOEQ==","shasum":"2b0cabc4d28489f682598605858a0782f14b154c","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.3.3.tgz"}},"2.4.0":{"name":"browserslist","version":"2.4.0","dependencies":{"caniuse-lite":"^1.0.30000718","electron-to-chromium":"^1.3.18"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.5.0","eslint-config-logux":"^16.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^20.0.3","eslint-plugin-node":"^5.1.1","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^20.0.4","lint-staged":"^4.0.4","pre-commit":"^1.1.3","size-limit":"^0.10.0","yaspeller-ci":"^0.6.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-aM2Gt4x9bVlCUteADBS6JP0F+2tMWKM1jQzUulVROtdFWFIcIVvY76AJbr7GDqy0eDhn+PcnpzzivGxY4qiaKQ==","shasum":"693ee93d01e66468a6348da5498e011f578f87f8","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.4.0.tgz"}},"2.5.0":{"name":"browserslist","version":"2.5.0","dependencies":{"caniuse-lite":"^1.0.30000744","electron-to-chromium":"^1.3.24"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.8.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.0","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.2.3","pre-commit":"^1.1.3","size-limit":"^0.11.6","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-6Vw1LIigGw8zCK0gxczksUMZlO+oPUwBazAztMmFL/F8D5wB0qCuxRJGYgYM3JzaO0v2ZMRIg+nnnOgNsPGHeA==","shasum":"0ea00d22813a4dfae5786485225a9c584b3ef37c","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.5.0.tgz"}},"2.5.1":{"name":"browserslist","version":"2.5.1","dependencies":{"caniuse-lite":"^1.0.30000744","electron-to-chromium":"^1.3.24"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.8.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.7.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.0","eslint-plugin-promise":"^3.5.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.2.3","pre-commit":"^1.1.3","size-limit":"^0.11.6","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-jAvM2ku7YDJ+leAq3bFH1DE0Ylw+F+EQDq4GkqZfgPEqpWYw9ofQH85uKSB9r3Tv7XDbfqVtE+sdvKJW7IlPJA==","shasum":"68e4bc536bbcc6086d62843a2ffccea8396821c6","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.5.1.tgz"}},"2.6.0":{"name":"browserslist","version":"2.6.0","dependencies":{"caniuse-lite":"^1.0.30000755","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.10.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.3.0","pre-commit":"^1.1.3","size-limit":"^0.12.0","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-XgAVmla9QAC5VkNmJ+i5zbgh+sPumLEL83MDYR9J8LoCJ1NgkptAqIny0+2VyI83OAnVHLdCsUjM4vs8RLsppQ==","shasum":"15b14ab7b7df4b108979585badff121eca9e1835","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.6.0.tgz"}},"2.6.1":{"name":"browserslist","version":"2.6.1","dependencies":{"caniuse-lite":"^1.0.30000755","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.10.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.3.0","pre-commit":"^1.1.3","size-limit":"^0.12.0","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-HBZwVT7ciQB9KlXM3AUMQbnQXtHWPsEUKQTiS0BEFfY5bOrMl94ORaqQD1GyuTGh69ZmYeue9QBqiw219e09eQ==","shasum":"cc65a05ad6131ebda26f076f2822ba1bc826376b","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.6.1.tgz"}},"2.7.0":{"name":"browserslist","version":"2.7.0","dependencies":{"caniuse-lite":"^1.0.30000757","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.10.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.3.0","pre-commit":"^1.1.3","size-limit":"^0.12.1","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-s34mrlczJsfbJu//mz/m9zlOy/S6tiP6El1u8iC1gTfEnzKXvxo8RAoCxS/MmojB7rd7bnfYzvKQNHykWaUWWw==","shasum":"dc375dc70048fec3d989042a35022342902eff00","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.7.0.tgz"}},"2.8.0":{"name":"browserslist","version":"2.8.0","dependencies":{"caniuse-lite":"^1.0.30000758","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.10.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.2.0","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^4.3.0","pre-commit":"^1.1.3","size-limit":"^0.13.1","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-iiWHM1Et6Q4TQpB7Ar6pxuM3TNMXasVJY4Y/oh3q38EwR3Z+IdZ9MyVf7PI4MJFB4xpwMcZgs9bEUnPG2E3TCA==","shasum":"27d64028130a2e8585ca96f7c3b7730eff4de493","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.8.0.tgz"}},"2.9.0":{"name":"browserslist","version":"2.9.0","dependencies":{"caniuse-lite":"^1.0.30000760","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.11.0","eslint-config-logux":"^16.2.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.3.2","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^5.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.1","yaspeller-ci":"^0.7.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-vJEBcDTANoDhSHL46NeOEW5hvQw7It9uCqzeFPQhpawXfnOwnpvW5C97vn1eGJ7iCkSg8wWU0nYObE7d/N95Iw==","shasum":"706aca15c53be15610f466e348cbfa0c00a6a379","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.9.0.tgz"}},"2.9.1":{"name":"browserslist","version":"2.9.1","dependencies":{"caniuse-lite":"^1.0.30000770","electron-to-chromium":"^1.3.27"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.11.0","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.3.2","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^5.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.2","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-3n3nPdbUqn3nWmsy4PeSQthz2ja1ndpoXta+dwFFNhveGjMg6FXpWYe12vsTpNoXJbzx3j7GZXdtoVIdvh3JbA==","shasum":"b72d3982ab01b5cd24da62ff6d45573886aff275","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.9.1.tgz"}},"2.10.0":{"name":"browserslist","version":"2.10.0","dependencies":{"caniuse-lite":"^1.0.30000780","electron-to-chromium":"^1.3.28"},"devDependencies":{"cross-spawn":"^5.1.0","eslint":"^4.12.1","eslint-ci":"^0.1.1","eslint-config-logux":"^17.0.0","eslint-config-standard":"^10.2.1","eslint-plugin-es5":"^1.1.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jest":"^21.4.1","eslint-plugin-node":"^5.2.1","eslint-plugin-promise":"^3.6.0","eslint-plugin-security":"^1.4.0","eslint-plugin-standard":"^3.0.1","jest":"^21.2.1","lint-staged":"^6.0.0","pre-commit":"^1.1.3","size-limit":"^0.13.2","yaspeller-ci":"^1.0.0"},"bin":{"browserslist":"./cli.js"},"_hasShrinkwrap":false,"directories":{},"dist":{"integrity":"sha512-WyvzSLsuAVPOjbljXnyeWl14Ae+ukAT8MUuagKVzIDvwBxl4UAwD1xqtyQs2eWYPGUKMeC3Ol62goqYuKqTTcw==","shasum":"bac5ee1cc69ca9d96403ffb8a3abdc5b6aed6346","tarball":"https://registry.npmjs.org/browserslist/-/browserslist-2.10.0.tgz"}}},"name":"browserslist","dist-tags":{"latest":"2.10.0"},"modified":"2017-12-06T18:43:00.408Z"} \ No newline at end of file diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/browserslist/-/browserslist-2.10.0.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/browserslist/-/browserslist-2.10.0.tgz.bin new file mode 100644 index 0000000000000000000000000000000000000000..88f7e45a70e45e75d7b2d61385317b33cde2ca54 GIT binary patch literal 14855 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 literal 0 HcmV?d00001 diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-api.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-api.bin new file mode 100644 index 0000000000..0f7d5383af --- /dev/null +++ b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-api.bin @@ -0,0 +1,21 @@ +HTTP/1.1 200 OK +Date: Mon, 11 Dec 2017 18:38:51 GMT +Content-Type: application/vnd.npm.install-v1+json +Content-Length: 8269 +Connection: keep-alive +Set-Cookie: __cfduid=d88832e1949be97719a1f327c4bc4f7421513017531; expires=Tue, 11-Dec-18 18:38:51 GMT; path=/; domain=.yarnpkg.com; HttpOnly +Cache-Control: max-age=300 +Last-Modified: Wed, 3 May 2017 9:12:01 GMT +ETag: "59099ee1-204d" +Accept-Ranges: bytes +Via: 1.1 varnish +Age: 2254 +X-Served-By: cache-mdw17347-MDW +X-Cache: HIT +X-Cache-Hits: 1 +X-Timer: S1513017532.519062,VS0,VE0 +Vary: Accept-Encoding, Accept +Server: cloudflare-nginx +CF-RAY: 3cba9033fd705625-ORD + +{"versions":{"0.1.0":{"name":"caniuse-api","version":"0.1.0","dependencies":{"browserslist":"^0.1.0","caniuse-db":"^1.0.30000030","lodash.memoize":"^2.4.1","lodash.uniq":"^2.4.1"},"devDependencies":{"6to5":"^1.14.17","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2363d7908466950f57637a2861c3d53dd6003a55","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-0.1.0.tgz"}},"1.0.0":{"name":"caniuse-api","version":"1.0.0","dependencies":{"browserslist":"^0.1.0","caniuse-db":"^1.0.30000030","lodash.memoize":"^2.4.1","lodash.uniq":"^2.4.1"},"devDependencies":{"6to5":"^1.14.17","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"392efe3eaea6a46ee9ee058f47d33c6dc9607923","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.0.0.tgz"}},"1.1.0":{"name":"caniuse-api","version":"1.1.0","dependencies":{"browserslist":"^0.2.0","caniuse-db":"^1.0.30000030","lodash.memoize":"^2.4.1","lodash.uniq":"^2.4.1"},"devDependencies":{"6to5":"^1.14.17","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2969d343a6871d950b28d341f15a750227e2210b","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.1.0.tgz"}},"1.2.0":{"name":"caniuse-api","version":"1.2.0","dependencies":{"browserslist":"^0.2.0","caniuse-db":"^1.0.30000030","lodash.memoize":"^2.4.1","lodash.uniq":"^2.4.1"},"devDependencies":{"6to5":"^1.14.17","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1803b57e3327e27baa91997b3f21b52a7625e967","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.2.0.tgz"}},"1.2.1":{"name":"caniuse-api","version":"1.2.1","dependencies":{"browserslist":"^0.2.0","caniuse-db":"^1.0.30000030","lodash.memoize":"^2.4.1","lodash.uniq":"^2.4.1"},"devDependencies":{"6to5":"^1.14.17","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"264bafaf1a5badbfb76f891bd4d285d4ad135cf7","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.2.1.tgz"}},"1.2.2":{"name":"caniuse-api","version":"1.2.2","dependencies":{"browserslist":"^0.2.0","caniuse-db":"^1.0.30000030","lodash.memoize":"^2.4.1","lodash.uniq":"^2.4.1","shelljs":"^0.3.0"},"devDependencies":{"6to5":"^1.14.17","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"627c88d0f7f818eac8cd6b424e2874fde7e72f1e","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.2.2.tgz"}},"1.3.0":{"name":"caniuse-api","version":"1.3.0","dependencies":{"browserslist":"^0.2.0","caniuse-db":"^1.0.30000030","lodash.memoize":"^2.4.1","lodash.uniq":"^2.4.1","shelljs":"^0.3.0"},"devDependencies":{"babel":"^4.7.16","babel-tape-runner":"^1.0.0","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"0181b686fbbaf48791e2c35fdab76f616a21a593","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.3.0.tgz"}},"1.3.1":{"name":"caniuse-api","version":"1.3.1","dependencies":{"browserslist":"^0.2.0","caniuse-db":"^1.0.30000030","lodash.memoize":"^2.4.1","lodash.uniq":"^2.4.1","shelljs":"^0.3.0"},"devDependencies":{"babel":"^4.7.16","babel-tape-runner":"^1.0.0","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"74fcf47e119dfc619237d9f3a7e98699781008ea","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.3.1.tgz"}},"1.3.2":{"name":"caniuse-api","version":"1.3.2","dependencies":{"browserslist":"^0.4.0","caniuse-db":"^1.0.30000030","lodash.memoize":"^2.4.1","lodash.uniq":"^3.1.0","shelljs":"^0.3.0"},"devDependencies":{"babel":"^4.7.16","babel-tape-runner":"^1.0.0","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"742c3e194ccb3bcbdb3cb492b511a47499d79e96","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.3.2.tgz"}},"1.4.0":{"name":"caniuse-api","version":"1.4.0","dependencies":{"browserslist":"^1.0.1","caniuse-db":"^1.0.30000346","lodash.memoize":"^2.4.1","lodash.uniq":"^3.1.0","shelljs":"^0.5.3"},"devDependencies":{"babel":"^4.7.16","babel-tape-runner":"^1.0.0","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"422227e1fc3176b6f94f70c3e991f67c61cd5b2b","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.4.0.tgz"}},"1.4.1":{"name":"caniuse-api","version":"1.4.1","dependencies":{"browserslist":"^1.0.1","caniuse-db":"^1.0.30000346","lodash.memoize":"^2.4.1","lodash.uniq":"^3.1.0","shelljs":"^0.5.3"},"devDependencies":{"babel":"^4.7.16","babel-tape-runner":"^1.0.0","jshint":"^2.5.10","tap-spec":"^2.1.1","tape":"^3.0.3"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"47f9c1ba01428681e13cd9e62f38daeda1a2495c","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.4.1.tgz"}},"1.5.0":{"name":"caniuse-api","version":"1.5.0","dependencies":{"browserslist":"^1.0.1","caniuse-db":"^1.0.30000346","lodash.memoize":"^4.1.0","lodash.uniq":"^4.3.0","shelljs":"^0.7.0"},"devDependencies":{"babel":"^4.7.16","babel-tape-runner":"^1.3.1","jshint":"^2.5.10","tap-spec":"^4.1.1","tape":"^4.5.1"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e0a6d8cdaf7229baf0552530c23c6bc4df9bf0ef","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.5.0.tgz"}},"1.5.1":{"name":"caniuse-api","version":"1.5.1","dependencies":{"browserslist":"^1.0.1","caniuse-db":"^1.0.30000346","lodash.memoize":"^4.1.0","lodash.uniq":"^4.3.0","shelljs":"^0.7.0"},"devDependencies":{"babel":"^4.7.16","babel-tape-runner":"^1.3.1","jshint":"^2.5.10","npmpub":"^3.1.0","tap-spec":"^4.1.1","tape":"^4.5.1"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"8edb536c41e2a3d0e5e960538a8398f00be46b27","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.5.1.tgz"}},"1.5.2":{"name":"caniuse-api","version":"1.5.2","dependencies":{"browserslist":"^1.0.1","caniuse-db":"^1.0.30000346","lodash.memoize":"^4.1.0","lodash.uniq":"^4.3.0","shelljs":"^0.7.0"},"devDependencies":{"babel":"^4.7.16","babel-tape-runner":"^1.3.1","jshint":"^2.5.10","npmpub":"^3.1.0","tap-spec":"^4.1.1","tape":"^4.5.1"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"8f393c682f661c0a997b77bba6e826483fb3600e","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.5.2.tgz"}},"1.5.3":{"name":"caniuse-api","version":"1.5.3","dependencies":{"browserslist":"^1.0.1","caniuse-db":"^1.0.30000346","lodash.memoize":"^4.1.0","lodash.uniq":"^4.3.0"},"devDependencies":{"babel-cli":"^6.22.2","babel-eslint":"^5.0.0","babel-preset-latest":"^6.22.0","babel-tape-runner":"^2.0.1","jshint":"^2.5.10","npmpub":"^3.1.0","tap-spec":"^4.1.1","tape":"^4.5.1"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"5018e674b51c393e4d50614275dc017e27c4a2a2","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.5.3.tgz"}},"1.6.1":{"name":"caniuse-api","version":"1.6.1","dependencies":{"browserslist":"^1.3.6","caniuse-db":"^1.0.30000529","lodash.memoize":"^4.1.2","lodash.uniq":"^4.5.0"},"devDependencies":{"babel-cli":"^6.22.2","babel-eslint":"^5.0.0","babel-preset-latest":"^6.22.0","babel-tape-runner":"^2.0.1","jshint":"^2.5.10","npmpub":"^3.1.0","tap-spec":"^4.1.1","tape":"^4.6.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b534e7c734c4f81ec5fbe8aca2ad24354b962c6c","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz"}},"2.0.0":{"name":"caniuse-api","version":"2.0.0","dependencies":{"browserslist":"^2.0.0","caniuse-lite":"^1.0.0","lodash.memoize":"^4.1.2","lodash.uniq":"^4.5.0"},"devDependencies":{"babel-cli":"^6.22.2","babel-eslint":"^5.0.0","babel-preset-latest":"^6.22.0","babel-tape-runner":"^2.0.1","jshint":"^2.5.10","npmpub":"^3.1.0","tap-spec":"^4.1.1","tape":"^4.6.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b1ddb5a5966b16f48dc4998444d4bbc6c7d9d834","tarball":"https://registry.npmjs.org/caniuse-api/-/caniuse-api-2.0.0.tgz"}}},"name":"caniuse-api","dist-tags":{"latest":"2.0.0"},"modified":"2017-05-03T09:12:01.052Z"} \ No newline at end of file diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-api/-/caniuse-api-2.0.0.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-api/-/caniuse-api-2.0.0.tgz.bin new file mode 100644 index 0000000000000000000000000000000000000000..a400158e4cc013a3c8052eb0fe812467fae74b2f GIT binary patch literal 4959 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 GA^AVduQK=m literal 0 HcmV?d00001 diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-lite.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-lite.bin new file mode 100644 index 0000000000..7229b6981f --- /dev/null +++ b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-lite.bin @@ -0,0 +1,21 @@ +HTTP/1.1 200 OK +Date: Mon, 11 Dec 2017 18:38:52 GMT +Content-Type: application/vnd.npm.install-v1+json +Content-Length: 96186 +Connection: keep-alive +Set-Cookie: __cfduid=d939a285946350410a19e2773d98c8f1a1513017532; expires=Tue, 11-Dec-18 18:38:52 GMT; path=/; domain=.yarnpkg.com; HttpOnly +Cache-Control: max-age=300 +Last-Modified: Sun, 10 Dec 2017 7:01:15 GMT +ETag: "5a2cdbbb-177ba" +Accept-Ranges: bytes +Via: 1.1 varnish +Age: 11870 +X-Served-By: cache-mdw17343-MDW +X-Cache: HIT +X-Cache-Hits: 1 +X-Timer: S1513017532.087176,VS0,VE1 +Vary: Accept-Encoding, Accept +Server: cloudflare-nginx +CF-RAY: 3cba90378af671d9-ORD + +{"versions":{"0.1.0":{"name":"caniuse-lite","version":"0.1.0","devDependencies":{"all-contributors-cli":"^3.0.7","alphanum-sort":"^1.0.2","ava":"^0.17.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","caniuse-db":"^1.0.30000605","del-cli":"^0.2.1","json-loader":"^0.5.4","nyc":"^10.1.2","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","timsort":"^0.3.0","webpack":"^1.14.0","webpack-bundle-analyzer":"^2.2.1"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"22360b6b6803dd211d60415162f0ec33a0a66157","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-0.1.0.tgz"}},"0.2.0":{"name":"caniuse-lite","version":"0.2.0","devDependencies":{"all-contributors-cli":"^3.0.7","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","caniuse-db":"1.0.30000649","del-cli":"^0.2.1","jest":"^19.0.2","listr":"^0.11.0","mz":"^2.6.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9f2731421eb1638cbdade62989176a5a69474128","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-0.2.0.tgz"}},"0.3.0":{"name":"caniuse-lite","version":"0.3.0","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","caniuse-db":"1.0.30000653","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"7e182363d002b23e167a8e8f6082147ce7453627","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-0.3.0.tgz"}},"1.0.30000655":{"name":"caniuse-lite","version":"1.0.30000655","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","caniuse-db":"1.0.30000655","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"20613c829e27942b3441d47da4a4b9b67e056b57","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000655.tgz"}},"1.0.30000656":{"name":"caniuse-lite","version":"1.0.30000656","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000656","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e6beefead44e0b6d82314fd42f57101270de41a7","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000656.tgz"}},"1.0.30000657":{"name":"caniuse-lite","version":"1.0.30000657","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000657","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"43ff22428ea436da7ed8cc38d418347944862f62","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000657.tgz"}},"1.0.30000659":{"name":"caniuse-lite","version":"1.0.30000659","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000659","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"7eeac0aac71930ba95912c61ec69baa3301a330c","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000659.tgz"}},"1.0.30000660":{"name":"caniuse-lite","version":"1.0.30000660","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000660","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"49f8572c3763b64aca221ac2b4da87bc214f759c","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000660.tgz"}},"1.0.30000661":{"name":"caniuse-lite","version":"1.0.30000661","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000661","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"d0de936b38e037f76803150ff1ad2914d17c9c36","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000661.tgz"}},"1.0.30000662":{"name":"caniuse-lite","version":"1.0.30000662","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000662","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"4b3af71d1c13ce9dfcbc6bc7830afac958ad19ca","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000662.tgz"}},"1.0.30000663":{"name":"caniuse-lite","version":"1.0.30000663","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000663","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"fc34de11ddc9289510be92ad8a277976497d1a96","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000663.tgz"}},"1.0.30000664":{"name":"caniuse-lite","version":"1.0.30000664","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000664","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"33f5a8eed8c78caa89de2df592913570b3a4f6fb","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000664.tgz"}},"1.0.30000665":{"name":"caniuse-lite","version":"1.0.30000665","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000665","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"62cf1283afb9b7b42d5ddceeb0345ce1ec432a1e","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000665.tgz"}},"1.0.30000666":{"name":"caniuse-lite","version":"1.0.30000666","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000666","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"831b63247e24fa408e20c6c546c4173d27c5a1a5","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000666.tgz"}},"1.0.30000667":{"name":"caniuse-lite","version":"1.0.30000667","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000667","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"dcbf8f19fa3b7ef447e7d514170a9ef949f4e347","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000667.tgz"}},"1.0.30000668":{"name":"caniuse-lite","version":"1.0.30000668","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000668","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e48b1a95270e3a0245fb2f90a2b89702599bdf98","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000668.tgz"}},"1.0.30000669":{"name":"caniuse-lite","version":"1.0.30000669","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000669","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"f312f4868722f3ce869ce934da3b536e0e393845","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000669.tgz"}},"1.0.30000670":{"name":"caniuse-lite","version":"1.0.30000670","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000670","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"c94f7dbf0b68eaadc46d3d203f46e82e7801135e","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000670.tgz"}},"1.0.30000671":{"name":"caniuse-lite","version":"1.0.30000671","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000671","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"c206c2f1a1feb34de46064407c4356818389bf1e","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000671.tgz"}},"1.0.30000672":{"name":"caniuse-lite","version":"1.0.30000672","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000672","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"3f89b9907db78653f88bc4d056ed626e8ec74357","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000672.tgz"}},"1.0.30000673":{"name":"caniuse-lite","version":"1.0.30000673","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000673","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"4f1c5fefb304f712c526614d83b19476c16e662a","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000673.tgz"}},"1.0.30000674":{"name":"caniuse-lite","version":"1.0.30000674","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000674","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"3eabc5e40ae2dce6375dd292f116b9e25bd505a7","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000674.tgz"}},"1.0.30000676":{"name":"caniuse-lite","version":"1.0.30000676","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000676","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1e962123f48073f0c51c4ea0651dd64d25786498","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000676.tgz"}},"1.0.30000677":{"name":"caniuse-lite","version":"1.0.30000677","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000677","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"43090233d4b2c7190657f95455983d94d264baaa","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000677.tgz"}},"1.0.30000679":{"name":"caniuse-lite","version":"1.0.30000679","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000679","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"0fb5bb3658d4d4448f8f86a1c48df15664aa05ef","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000679.tgz"}},"1.0.30000680":{"name":"caniuse-lite","version":"1.0.30000680","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000680","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"d94d81294471617e86500f0aab90f11d22bc8934","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000680.tgz"}},"1.0.30000683":{"name":"caniuse-lite","version":"1.0.30000683","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000683","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"a7573707cf2acc9217ca6484d1dfbc9f13898364","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000683.tgz"}},"1.0.30000684":{"name":"caniuse-lite","version":"1.0.30000684","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000684","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"0c1032d0b36e14d1ac199f93ef2d1c42d3f03fd7","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000684.tgz"}},"1.0.30000686":{"name":"caniuse-lite","version":"1.0.30000686","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000686","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"d9d9ec6110e5533be544a689003f7596532c67d3","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000686.tgz"}},"1.0.30000687":{"name":"caniuse-lite","version":"1.0.30000687","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000687","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"06763368260f5257e0c98f2b0c8d23cca4c160bb","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000687.tgz"}},"1.0.30000688":{"name":"caniuse-lite","version":"1.0.30000688","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000688","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"95036716b9459bb7471aba617516461ff562b359","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000688.tgz"}},"1.0.30000689":{"name":"caniuse-lite","version":"1.0.30000689","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000689","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"729b6fc3afb0d92df93e0aafd539367e771a0fd6","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000689.tgz"}},"1.0.30000690":{"name":"caniuse-lite","version":"1.0.30000690","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000690","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"3b232dbc0cf32bc2a888ec199852a50afa37f5ef","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000690.tgz"}},"1.0.30000692":{"name":"caniuse-lite","version":"1.0.30000692","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000692","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"34600fd7152352d85a47f4662a3b51b02d8b646f","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000692.tgz"}},"1.0.30000693":{"name":"caniuse-lite","version":"1.0.30000693","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000693","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"c9c6298697c71fdf6cb13eefe8aa93926f2f8613","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000693.tgz"}},"1.0.30000694":{"name":"caniuse-lite","version":"1.0.30000694","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000694","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1492dab7c10c608c9d37a723e6e3e7873e0ce94f","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000694.tgz"}},"1.0.30000695":{"name":"caniuse-lite","version":"1.0.30000695","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000695","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"0c2f711d49b9979884fa74349888aa48a8689dfd","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000695.tgz"}},"1.0.30000696":{"name":"caniuse-lite","version":"1.0.30000696","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000696","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"30f2695d2a01a0dfd779a26ab83f4d134b3da5cc","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000696.tgz"}},"1.0.30000697":{"name":"caniuse-lite","version":"1.0.30000697","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000697","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"125fb00604b63fbb188db96a667ce2922dcd6cdd","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000697.tgz"}},"1.0.30000698":{"name":"caniuse-lite","version":"1.0.30000698","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000698","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"8102e8978b1f36962f2a102432e4bf4eac7b6cbe","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000698.tgz"}},"1.0.30000699":{"name":"caniuse-lite","version":"1.0.30000699","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000699","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2a187b737edaa9ebedbbb56edcb53e994eceda0c","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000699.tgz"}},"1.0.30000700":{"name":"caniuse-lite","version":"1.0.30000700","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000700","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"6084871ec75c6fa62327de97622514f95d9db26a","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000700.tgz"}},"1.0.30000701":{"name":"caniuse-lite","version":"1.0.30000701","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000701","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9d673cf6b74dcb3d5c21d213176b011ac6a45baa","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000701.tgz"}},"1.0.30000702":{"name":"caniuse-lite","version":"1.0.30000702","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000702","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"bd66e40345528fe0c001917d1d3f55454df634f1","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000702.tgz"}},"1.0.30000703":{"name":"caniuse-lite","version":"1.0.30000703","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000703","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"666e8c3f1e4f7abb1d16d48e04e7e9e8df934925","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000703.tgz"}},"1.0.30000704":{"name":"caniuse-lite","version":"1.0.30000704","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000704","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","np":"^2.13.1","remark":"^7.0.0","rollup":"^0.41.4","rollup-plugin-buble":"^0.15.0","rollup-plugin-cleanup":"^1.0.0","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","webpack":"^2.0.0","webpack-bundle-analyzer":"^2.0.0","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"adb6ea01134515663682db93abab291d4c02946b","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000704.tgz"}},"1.0.30000706":{"name":"caniuse-lite","version":"1.0.30000706","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000706","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"bc59abc41ba7d4a3634dda95befded6114e1f24e","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000706.tgz"}},"1.0.30000708":{"name":"caniuse-lite","version":"1.0.30000708","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000708","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"71dbf388c57f379b1bb66c89a890edc04c2509b6","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000708.tgz"}},"1.0.30000709":{"name":"caniuse-lite","version":"1.0.30000709","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000709","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e027c7a0dfd5ada58f931a1080fc71965375559b","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000709.tgz"}},"1.0.30000710":{"name":"caniuse-lite","version":"1.0.30000710","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000710","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1c249bf7c6a61161c9b10906e3ad9fa5b6761af1","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000710.tgz"}},"1.0.30000711":{"name":"caniuse-lite","version":"1.0.30000711","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000711","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"90f632a4ede34d40b3e49622e58e710dc187ef6c","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000711.tgz"}},"1.0.30000712":{"name":"caniuse-lite","version":"1.0.30000712","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000712","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b4732def2459224f3f78c6a9ba103abfcc705670","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000712.tgz"}},"1.0.30000713":{"name":"caniuse-lite","version":"1.0.30000713","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000713","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"33957ecb4a2154a5d40a60d13d8bf1cfa0881a8a","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000713.tgz"}},"1.0.30000714":{"name":"caniuse-lite","version":"1.0.30000714","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000714","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e7e5b43172f20c9fdc2f1e4204b37140c447739f","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000714.tgz"}},"1.0.30000715":{"name":"caniuse-lite","version":"1.0.30000715","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000715","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"c327f5e6d907ebcec62cde598c3bf0dd793fb9a0","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000715.tgz"}},"1.0.30000716":{"name":"caniuse-lite","version":"1.0.30000716","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000716","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2b40dd4a7edb7f0c468643b899b832b315988e6a","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000716.tgz"}},"1.0.30000717":{"name":"caniuse-lite","version":"1.0.30000717","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000717","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"4539b126af787c1d4851944de22b2bd8780d3612","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000717.tgz"}},"1.0.30000718":{"name":"caniuse-lite","version":"1.0.30000718","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000718","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"0dd24290beb11310b2d80f6b70a823c2a65a6fad","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000718.tgz"}},"1.0.30000720":{"name":"caniuse-lite","version":"1.0.30000720","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000720","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9313aba5b923fab5c78f6054819b6f0cbc626352","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000720.tgz"}},"1.0.30000721":{"name":"caniuse-lite","version":"1.0.30000721","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000721","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"931a21a7bd85016300328d21f126d84b73437d35","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000721.tgz"}},"1.0.30000722":{"name":"caniuse-lite","version":"1.0.30000722","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000722","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"8cbfe07440478e3a16ab0d3b182feef1901eab55","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000722.tgz"}},"1.0.30000723":{"name":"caniuse-lite","version":"1.0.30000723","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000723","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"f9db1e2868caf097b00265ac2e71ba44b608fb1e","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000723.tgz"}},"1.0.30000724":{"name":"caniuse-lite","version":"1.0.30000724","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000724","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b9711be59257bdbce6a872ade51a11e864c21ec1","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000724.tgz"}},"1.0.30000725":{"name":"caniuse-lite","version":"1.0.30000725","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000725","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"4fa66372323c6ff46c8a1ba03f9dcd73d7a1cb39","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000725.tgz"}},"1.0.30000726":{"name":"caniuse-lite","version":"1.0.30000726","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000726","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"966a753fa107a09d4131cf8b3d616723a06ccf7e","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000726.tgz"}},"1.0.30000727":{"name":"caniuse-lite","version":"1.0.30000727","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000727","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"20c895768398ded5f98a4beab4a76c285def41d2","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000727.tgz"}},"1.0.30000730":{"name":"caniuse-lite","version":"1.0.30000730","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000730","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"26a14ff1b3bfc1f1cb4da75c2c73451b3f1ade1a","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000730.tgz"}},"1.0.30000731":{"name":"caniuse-lite","version":"1.0.30000731","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000731","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"6f2b9096285af3c7bcf2abe39647bb525d68c842","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000731.tgz"}},"1.0.30000732":{"name":"caniuse-lite","version":"1.0.30000732","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000732","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"7cf9ca565f4d31a4b3dfa6e26b72ec22e9027da1","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000732.tgz"}},"1.0.30000733":{"name":"caniuse-lite","version":"1.0.30000733","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000733","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"ebfc48254117cc0c66197a4536cb4397a6cfbccd","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000733.tgz"}},"1.0.30000734":{"name":"caniuse-lite","version":"1.0.30000734","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000734","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"492791fb0557978fcc1b7a8f486270b35ea6e569","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000734.tgz"}},"1.0.30000735":{"name":"caniuse-lite","version":"1.0.30000735","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000735","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"aab44016ef243e215ef43fd1343efd22930842f8","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000735.tgz"}},"1.0.30000736":{"name":"caniuse-lite","version":"1.0.30000736","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000736","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"df369dfb7ed4d77a8a01244252c6e2f7db9cc689","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000736.tgz"}},"1.0.30000737":{"name":"caniuse-lite","version":"1.0.30000737","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000737","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"8199a601dd54c096e1f8567bcb7461b94f0d4509","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000737.tgz"}},"1.0.30000738":{"name":"caniuse-lite","version":"1.0.30000738","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000738","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1820c3c9adb9a117e311a5bdca1d25bc34288eba","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000738.tgz"}},"1.0.30000739":{"name":"caniuse-lite","version":"1.0.30000739","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000739","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9ee8c7016f5c522dbb0c0863d55c61efb453ae95","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000739.tgz"}},"1.0.30000740":{"name":"caniuse-lite","version":"1.0.30000740","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000740","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"f2c4c04d6564eb812e61006841700ad557f6f973","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000740.tgz"}},"1.0.30000741":{"name":"caniuse-lite","version":"1.0.30000741","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000741","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"bc526bc2046e6bc38737cfd77d3026ef04b8f464","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000741.tgz"}},"1.0.30000742":{"name":"caniuse-lite","version":"1.0.30000742","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000742","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b5ac8a4a6f36e40a33a6188a8a8bdf8460c32d25","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000742.tgz"}},"1.0.30000743":{"name":"caniuse-lite","version":"1.0.30000743","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000743","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"f4f5c6750676ff8f6144ea40456c3729d5341769","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000743.tgz"}},"1.0.30000744":{"name":"caniuse-lite","version":"1.0.30000744","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000744","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"860fa5c83ba34fe619397d607f30bb474821671b","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000744.tgz"}},"1.0.30000745":{"name":"caniuse-lite","version":"1.0.30000745","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000745","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"20d6fede1157a4935133502946fc7e0e6b880da5","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000745.tgz"}},"1.0.30000746":{"name":"caniuse-lite","version":"1.0.30000746","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000746","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"c64f95a3925cfd30207a308ed76c1ae96ea09ea0","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000746.tgz"}},"1.0.30000747":{"name":"caniuse-lite","version":"1.0.30000747","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000747","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"da86e78e12d0641abeeaee6ecd55d81bd9bd3b5d","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000747.tgz"}},"1.0.30000748":{"name":"caniuse-lite","version":"1.0.30000748","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000748","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"44c8d6da52ad65a5d7b9dca4efebd0bdd982ba09","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000748.tgz"}},"1.0.30000749":{"name":"caniuse-lite","version":"1.0.30000749","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000749","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2ff382865aead8cca35dacfbab04f58effa4c01c","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000749.tgz"}},"1.0.30000750":{"name":"caniuse-lite","version":"1.0.30000750","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000750","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"38ad19aa4c6d88da38e8900d3666b4e3bbb65c22","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000750.tgz"}},"1.0.30000751":{"name":"caniuse-lite","version":"1.0.30000751","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000751","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"298ad34182ca4359757b4a93afc681b7b917e358","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000751.tgz"}},"1.0.30000752":{"name":"caniuse-lite","version":"1.0.30000752","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000752","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"0a79df520669d92ddc7f57406eed935948263130","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000752.tgz"}},"1.0.30000753":{"name":"caniuse-lite","version":"1.0.30000753","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000753","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"10d7683272edf94e5f4a8e94710e60c218f6ced7","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000753.tgz"}},"1.0.30000755":{"name":"caniuse-lite","version":"1.0.30000755","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000755","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9ce5f6e06bd75ec8209abe8853c3beef02248d65","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000755.tgz"}},"1.0.30000756":{"name":"caniuse-lite","version":"1.0.30000756","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000756","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"3da701c1521b9fab87004c6de7c97fa47dbeaad2","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000756.tgz"}},"1.0.30000757":{"name":"caniuse-lite","version":"1.0.30000757","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000757","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"81e3bc029728a032933501994ef79db1c21159e3","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000757.tgz"}},"1.0.30000758":{"name":"caniuse-lite","version":"1.0.30000758","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000758","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e261140076651049cf6891ed4bc649b5c8c26c69","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000758.tgz"}},"1.0.30000760":{"name":"caniuse-lite","version":"1.0.30000760","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000760","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"ec720395742f1c7ec8947fd6dd2604e77a8f98ff","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000760.tgz"}},"1.0.30000762":{"name":"caniuse-lite","version":"1.0.30000762","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000762","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"0591eaee7e1fc3d95399a8869f2e00092c16ecd9","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000762.tgz"}},"1.0.30000764":{"name":"caniuse-lite","version":"1.0.30000764","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000764","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"97ea7472f9d3e691eede34f21983cfc219ac7842","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000764.tgz"}},"1.0.30000765":{"name":"caniuse-lite","version":"1.0.30000765","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000765","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"aa1a75019276b48463c0fca2a5257fb9f26a7c9d","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000765.tgz"}},"1.0.30000766":{"name":"caniuse-lite","version":"1.0.30000766","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000766","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"8a095cc5eb9923c27008ce4d0db23e65a3e28843","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000766.tgz"}},"1.0.30000769":{"name":"caniuse-lite","version":"1.0.30000769","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000769","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"d68c5aa0772ea3eac6c97d42e239c9b4d3261b93","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000769.tgz"}},"1.0.30000770":{"name":"caniuse-lite","version":"1.0.30000770","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000770","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"bc8e7f50b073273390db6ab357378909a14e9bdb","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000770.tgz"}},"1.0.30000772":{"name":"caniuse-lite","version":"1.0.30000772","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000772","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"78129622cabfed7af1ff38b64ab680a6a0865420","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000772.tgz"}},"1.0.30000774":{"name":"caniuse-lite","version":"1.0.30000774","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000774","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"60f4ecf5d45980e7ac5901f03ce67f1ae08df59f","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000774.tgz"}},"1.0.30000775":{"name":"caniuse-lite","version":"1.0.30000775","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000775","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"74d27feddc47f3c84cfbcb130c3092a35ebc2de2","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000775.tgz"}},"1.0.30000776":{"name":"caniuse-lite","version":"1.0.30000776","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000776","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"616d0f16fb8c7ac69f2ca344fbd501a24879816c","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000776.tgz"}},"1.0.30000777":{"name":"caniuse-lite","version":"1.0.30000777","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000777","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"31c18a4a8cd49782ebb305c8e8a93e6b3b3e4f13","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000777.tgz"}},"1.0.30000778":{"name":"caniuse-lite","version":"1.0.30000778","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000778","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"f1e7cb8b13b1f6744402291d75f0bcd4c3160369","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000778.tgz"}},"1.0.30000779":{"name":"caniuse-lite","version":"1.0.30000779","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000779","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"59285a00d3ce84361d2c668f251fe46baaeb951b","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000779.tgz"}},"1.0.30000780":{"name":"caniuse-lite","version":"1.0.30000780","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000780","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1f9095f2efd4940e0ba6c5992ab7a9b64cc35ba4","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000780.tgz"}},"1.0.30000781":{"name":"caniuse-lite","version":"1.0.30000781","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000781","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"d5afb556b65d19eb499ebd1a5ad990633f85cc68","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000781.tgz"}},"1.0.30000782":{"name":"caniuse-lite","version":"1.0.30000782","devDependencies":{"all-contributors-cli":"^3.0.7","any-observable":"^0.2.0","babel-cli":"^6.24.0","babel-generator":"^6.21.0","babel-preset-env":"^1.1.8","babel-register":"^6.18.0","babel-types":"^6.21.0","bunyan":"^1.8.10","caniuse-db":"1.0.30000782","del-cli":"^0.2.1","execa":"^0.6.3","fecha":"^2.3.0","gift":"^0.10.0","got":"^6.7.1","jest":"^19.0.2","listr":"^0.11.0","mdast-util-heading-range":"^2.0.1","mz":"^2.6.0","remark":"^7.0.0","size-limit":"^0.7.1","split":"^1.0.0","stream-to-observable":"^0.2.0","unist-builder":"^1.0.2","write-file-promise":"^1.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"5b82b8c385f25348745c471ca51320afb1b7f254","tarball":"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000782.tgz"}}},"name":"caniuse-lite","dist-tags":{"latest":"1.0.30000782"},"modified":"2017-12-10T07:01:15.681Z"} \ No newline at end of file diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000782.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000782.tgz.bin new file mode 100644 index 0000000000000000000000000000000000000000..46d37d38066fb5912a7c1e17a60a92b7b2db69ac GIT binary patch literal 236874 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 z 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%0ADfV_xX_=#ESn(8guDz)D5nh7~k`kUmbOkYv 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 literal 0 HcmV?d00001 diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/electron-to-chromium.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/electron-to-chromium.bin new file mode 100644 index 0000000000..a8df2b44d1 --- /dev/null +++ b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/electron-to-chromium.bin @@ -0,0 +1,21 @@ +HTTP/1.1 200 OK +Date: Mon, 11 Dec 2017 18:38:51 GMT +Content-Type: application/vnd.npm.install-v1+json +Content-Length: 14502 +Connection: keep-alive +Set-Cookie: __cfduid=d88832e1949be97719a1f327c4bc4f7421513017531; expires=Tue, 11-Dec-18 18:38:51 GMT; path=/; domain=.yarnpkg.com; HttpOnly +Cache-Control: max-age=300 +Last-Modified: Tue, 5 Dec 2017 9:02:18 GMT +ETag: "5a26609a-38a6" +Accept-Ranges: bytes +Via: 1.1 varnish +Age: 2862 +X-Served-By: cache-mdw17347-MDW +X-Cache: HIT +X-Cache-Hits: 2 +X-Timer: S1513017532.901913,VS0,VE0 +Vary: Accept-Encoding, Accept +Server: cloudflare-nginx +CF-RAY: 3cba90365f415625-ORD + +{"versions":{"1.0.0":{"name":"electron-to-chromium","version":"1.0.0","devDependencies":{"request":"^2.79.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"984a5364268933e7070f863c2a250720f78b01dc","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.0.0.tgz"}},"1.0.1":{"name":"electron-to-chromium","version":"1.0.1","devDependencies":{"request":"^2.79.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"0d792c55dc927110bec0feca989b5b2616df5b43","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.0.1.tgz"}},"1.1.0":{"name":"electron-to-chromium","version":"1.1.0","devDependencies":{"request":"^2.79.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"c0c5d5bed6843da24c0f68a4d5206207795afbf9","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.1.0.tgz"}},"1.1.1":{"name":"electron-to-chromium","version":"1.1.1","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"c27f9ec8e6bbbbe55e6076a1d9eec02519627b79","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.1.1.tgz"}},"1.2.0":{"name":"electron-to-chromium","version":"1.2.0","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"3bd7761f85bd4163602259ae6c7ed338050b17e7","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.0.tgz"}},"1.2.1":{"name":"electron-to-chromium","version":"1.2.1","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"63ac7579a1c5bedb296c8607621f2efc9a54b968","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.1.tgz"}},"1.2.2":{"name":"electron-to-chromium","version":"1.2.2","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e41bc9488c88e3cfa1e94bde28e8420d7d47c47c","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.2.tgz"}},"1.2.3":{"name":"electron-to-chromium","version":"1.2.3","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"4b4d04d237c301f72e2d15c2137b2b79f9f5ab76","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.3.tgz"}},"1.2.4":{"name":"electron-to-chromium","version":"1.2.4","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9751cbea89fa120bf88c226ba41eb8d0b6f1b597","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.4.tgz"}},"1.2.5":{"name":"electron-to-chromium","version":"1.2.5","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"d373727228843dfd8466c276089f13b40927a952","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.5.tgz"}},"1.2.6":{"name":"electron-to-chromium","version":"1.2.6","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"f38ad51d1919b06bc07275c62629db803ddca05a","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.6.tgz"}},"1.2.7":{"name":"electron-to-chromium","version":"1.2.7","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"4f748061407e478c76256d04496972b71f647407","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.7.tgz"}},"1.2.8":{"name":"electron-to-chromium","version":"1.2.8","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"22c2e6200d350da27d6050db7e3f6f85d18cf4ed","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.2.8.tgz"}},"1.3.0":{"name":"electron-to-chromium","version":"1.3.0","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"8fd5aee0eb85e024c3be88bfa99c8b560b661259","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.0.tgz"}},"1.3.1":{"name":"electron-to-chromium","version":"1.3.1","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"75697666b0abd80104577b53a96a6d06ca2b7f2c","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.1.tgz"}},"1.3.2":{"name":"electron-to-chromium","version":"1.3.2","devDependencies":{"request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b8ce5c93b308db0e92f6d0435c46ddec8f6363ab","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.2.tgz"}},"1.3.3":{"name":"electron-to-chromium","version":"1.3.3","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"651eb63fe89f39db70ffc8dbd5d9b66958bc6a0e","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.3.tgz"}},"1.3.4":{"name":"electron-to-chromium","version":"1.3.4","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e51769c0cf550e0cf5aedf6aa2b803a264b3a900","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.4.tgz"}},"1.3.5":{"name":"electron-to-chromium","version":"1.3.5","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"6cd6ff2106224a6130e235f21050f9546bc3e729","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.5.tgz"}},"1.3.6":{"name":"electron-to-chromium","version":"1.3.6","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b90ff7e9094e6f7dd343761a001e82592d937db2","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.6.tgz"}},"1.3.7":{"name":"electron-to-chromium","version":"1.3.7","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9fb75a2417f28114425d364de118d1cfd681432b","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.7.tgz"}},"1.3.8":{"name":"electron-to-chromium","version":"1.3.8","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b2c8a2c79bb89fbbfd3724d9555e15095b5f5fb6","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.8.tgz"}},"1.3.9":{"name":"electron-to-chromium","version":"1.3.9","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"db1cba2a26aebcca2f7f5b8b034554468609157d","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.9.tgz"}},"1.3.10":{"name":"electron-to-chromium","version":"1.3.10","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"63d62b785471f0d8dda85199d64579de8a449f08","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.10.tgz"}},"1.3.11":{"name":"electron-to-chromium","version":"1.3.11","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"744761df1d67b492b322ce9aa0aba5393260eb61","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.11.tgz"}},"1.3.12":{"name":"electron-to-chromium","version":"1.3.12","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"62f33e4a59b4855f0de4bb8972bf1b841b98b6d2","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.12.tgz"}},"1.3.13":{"name":"electron-to-chromium","version":"1.3.13","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1b3a5eace6e087bb5e257a100b0cbfe81b2891fc","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.13.tgz"}},"1.3.14":{"name":"electron-to-chromium","version":"1.3.14","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"64af0f9efd3c3c6acd57d71f83b49ca7ee9c4b43","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.14.tgz"}},"1.3.15":{"name":"electron-to-chromium","version":"1.3.15","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"08397934891cbcfaebbd18b82a95b5a481138369","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.15.tgz"}},"1.3.16":{"name":"electron-to-chromium","version":"1.3.16","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"d0e026735754770901ae301a21664cba45d92f7d","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.16.tgz"}},"1.3.17":{"name":"electron-to-chromium","version":"1.3.17","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"41c13457cc7166c5c15e767ae61d86a8cacdee5d","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.17.tgz"}},"1.3.18":{"name":"electron-to-chromium","version":"1.3.18","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"3dcc99da3e6b665f6abbc71c28ad51a2cd731a9c","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.18.tgz"}},"1.3.19":{"name":"electron-to-chromium","version":"1.3.19","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"73d97b0e8b05aa776cedf3cdce7fdc0538037675","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.19.tgz"}},"1.3.20":{"name":"electron-to-chromium","version":"1.3.20","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2eedd5ccbae7ddc557f68ad1fce9c172e915e4e5","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.20.tgz"}},"1.3.21":{"name":"electron-to-chromium","version":"1.3.21","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"a967ebdcfe8ed0083fc244d1894022a8e8113ea2","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.21.tgz"}},"1.3.22":{"name":"electron-to-chromium","version":"1.3.22","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"4322d52c151406e3eaef74ad02676883e8416418","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.22.tgz"}},"1.3.23":{"name":"electron-to-chromium","version":"1.3.23","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"e6668ab18cb69afb8f577c8a9fc23d002788be74","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.23.tgz"}},"1.3.24":{"name":"electron-to-chromium","version":"1.3.24","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9b7b88bb05ceb9fa016a177833cc2dde388f21b6","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz"}},"1.3.25":{"name":"electron-to-chromium","version":"1.3.25","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"453b21009836d0997d86035601ff6cae4791c460","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.25.tgz"}},"1.3.26":{"name":"electron-to-chromium","version":"1.3.26","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"996427294861a74d9c7c82b9260ea301e8c02d66","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.26.tgz"}},"1.3.27":{"name":"electron-to-chromium","version":"1.3.27","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"78ecb8a399066187bb374eede35d9c70565a803d","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz"}},"1.3.28":{"name":"electron-to-chromium","version":"1.3.28","devDependencies":{"ava":"^0.18.2","codecov":"^2.1.0","nyc":"^10.2.0","request":"^2.79.0","shelljs":"^0.7.6"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"8dd4e6458086644e9f9f0a1cf32e2a1f9dffd9ee","tarball":"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.28.tgz"}}},"name":"electron-to-chromium","dist-tags":{"latest":"1.3.28"},"modified":"2017-12-05T09:02:18.254Z"} \ No newline at end of file diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.28.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.28.tgz.bin new file mode 100644 index 0000000000000000000000000000000000000000..9a711e727aeac61e3a60e6e236809bd9c22de830 GIT binary patch literal 4479 zcmY+Ec{CK>-^Z0gmh7pa46V`8BpwX| znqs}Af%5V|T{MceBd-FKhrqxPn34ie-_(+gSqJNdM|UDqU{FXr2J0n@ zMd8tSkPqG)jr9CKoeA2@74HTEf*}y)zf~_Z>W>@-bVs9cAfyMz7tO|OK|85~#kyl? zJsliSF3tpuv$``9>g1w;c0nsCJ1HW;iby3VhzitML0MT*!O2M;3YAxq2h#|ZzzV8B zv_B5xjrLKuB%uG`gJ}35dC32RR|VpbcsF%fRiHE06N&LsmkB_6d*R$&Wl&g8RiFVL zk2CY~2%u3SQEq4&j~Ct>>j49LBK<)~SG2k!n3j|r8?y=02M;pEI%8ZgXlEGkucHDK zXo1H4i4qEwSAi+W!@%JG1O~T6y260Mib#}#qJq3Lh;}1kHfAjp3XQ{q%#mKMXdf8R zDFBc5VPm$!AYs5iPvT1h!}z$-bgr~S?f}R zR!{+%>RSI1{6&WW4Gd{d_1`Oy0R~UA0RJgiVm#5_FrdZ%CI^;L0?R2YDM(vc$Vpql zX}9}pLDQf-umoop52QC5lr=+Z)1Tr(%Wn*Sz z79=sz{T=k{0`5MO)$$HLEoWc2I`xqK&$V{GR=cJ5aB_5L`vv4A=b^|--1Ft1T{pTD zbHold?HZpgT)jE|{#{-XB-M?t;ftO0rB<1)-!NNZrrrEd)ggbQ*Xl~{-tkjpiY_N- z@VD_(W0YREeiGOy_qwz6u|%G9EOcO|M(DlkkS~J1;JC)SnsHBa>lh;BT>8=KV48Eh zr-%4ii9q-=5=rVQu;)!1nGTt){g_r=c!Q!#f2}O_f&Jooj^yZTv6FX2rOa+3S0qW* zB0JEBQP*t%2=pr9j$NhE7pWV0NjWx)nm2*PqrY={ZQV4^v;hVI^|N1+7P51v3Vl91 z3yRYZI2g7+aMs?5FYX^NkVyWgwb*`9*U4bcrKz{RQQS4{y}j1ITemqmT$5{F&o>|v z)}%xtwW)}y#fa?gF~ZOX3D#Pk1QoM}eXM}3h}OkvRvAEa2R;!5<-d4H$Pl_pwUwI zK27wM)DTim@C4ZZ>af0#pHqBvX|}4Tp40c(P)d~A^>I^n)rXfEUEcN93UE4?<|=l! zw7GW-`qZRK!duaH7D3tXm&^L_WJlR;lZlzdjRSDj-$r>*&at|xn_Bhx!}+xzljajW zjnWP^HgLf8LGHv%@s{n-pdS6rqoLAF!Qg|XCCY{5deQ%e@gzi>!^`QBAc6i)|ZY;%dR9f>LRnP3~ z5a@bKZR-+K9DN9re6R+w1}U3T8+gVk##zS(4e}t{S``LGl7tJ>NaY(xk7gr#4(p{> zJ$}@{YaQzj=`;pxlh#Z5pAM3GK2tK45LLCq8Y%XQ
glUV^^iFWYQ)aP5gFCMUy< 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 W*MH(eJzmV9(iN7!38J&2qx&!Y!) literal 0 HcmV?d00001 diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/loader-utils.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/loader-utils.bin index 265dd3b6b1d8a756837031af403a2395af428a7a..ec6a3b3176aaa169f7603b10ac31b0ef8ba8b65d 100644 GIT binary patch literal 10392 zcmd^FTW=e=6@EA1|1i*NH8KzHRNw;Jb=oYtX^PlLw|z*!%b`4uG!mq-H*S#r_8!X0 z#!8*+?C!XY8~DXDIvkSUxqgRya(4FDBbY$N8LOWC`S9SxcQ~z{F57VhP@Q0;U%*tL zrqWJ@ss8lz?C{{*W!quf)o0f$685XryotVRmhI71n+lio8z-fEIX-bCpFl;eLSjGzB@lYdQ_$5!Z+>l z)$7?LE*FogCtbIC*3PeKl|G&$t*7nQ%lWig_&2qm;W5p1c<{a7boJ9^YI1{V zTAf}JaH{&t@@j`0p9+|AcZ1vGGe4VFBjs{t(nHNP=cB`eZ(_t%S3mdd3^&s%Tz9xR zJb2OgX;oBnMXPEy=Oi~HIJ7F${!pLd`U+G1hwEt-x9eM^AHfK2>Zd1vD+1e9Ppc>2 zk-~OQ^^>Nf2?+Qf>a%8nYg+J6pxKE9shJqRIA!A(k7<$@eobHBt?qFfX_xJ6yn9iU zL@S_A#QE|v<+)#D-Oif!4FUGY`uR71pH?CU=X5d{wKL#d{p|V4;lbg-+Yt@ikk&V& z>Dv*Tz=V~5TED>2bTnW3gzNgUYv!BL_`N9oa3eS#C0t>fu#F9FKTs@8?S6kVdN&@u zI`^B?^L5j{{&DSBqiOc@4bnKWh}bRHH^WFSHJh$Xydn9^1$}|+OZ#AzVu+Dt77XYZ zRUoVLMoZutgmWlpS)E@8vTz!7PKL6X9v!W5M&Das7YDf5OqT1}(e14q)q9Wib~lr5 z_RrBfT1t6>z90b2e}5ow3}97G7^T(;B%xuLFiO zfd_7w<=i97N_ZW7FcfiQgru`lCUU34P$2MIAn?BKPz3MO5`+&F5v=xP^@dPLic7;# zJ7C&5o0DN$N?#T+fIHA`_CV91FL;(xudo@o z4u*1*reejbWUOLT%LJAJPbsNDY27gkgMp{_z%zZpGhZZlDF(FY5t*>jdqEWrWX`k_ zkUST}T99+&(ok+|_Q11!!Lwf^cs^;+3bH331I`Mkn2XyCk|XUN zc&;ya?hf#Nig7Om6=5ZTz2{Uf*+f#6d3Vr@OX6`vf=YCJNp%<{4jM`%$hYCLP$L>G zCQuU6kjaHee`GcRl4+uI#86Nng~*U>a8h}zd<2;yO*;tCZVzY*9X+$lHpqOOULF?I zl)E`s7Nyfv=|?NHWy&#WT?m$EkrkD`JP!snd_)2IbAY=@z{A4YmP9X62x68HJ##Kn zc}*P%p>?MG#i%M^RD%v>*5s}qx)0>Ny{QIC{%6_ru&~bFbFUaEExd?4x|F;!-rFb~ zMG=Z7RD>BnSSb(tga&#u8j^hISfghN1!n;rI7WzT!rK|1sISC>R8D(z)NdQiuJ?Hp zrJug>`Yz^l+pb|tFmbWGXg2kH+dM36iEZ03w=$;MzF39}YB$z?vuS2+Nrse2Kgl2d zN2yd`@_~Ec0z&}O1duCeV)lH}K>n@n9%3TawnvYh^eN;zAb za!}MXmPRW&!$3V4QG$J%3B7qHNq%*@u^P27lFkb`Q=T58CZ0giErW@SI~Q^gvXIC@ z=mC6Su{XJ(N4j~RG(N`;en~|8CHxFG^QNV9uMv?wxJgwvujG?NnY>WI&;X5ADVRX~p93tM{H1S;m zv`F^iA2))-x!J>3rlSUt3L+aIZm6j9p-iSq8e=p-{Wm74jg*m>HpC#x+_9J*%IrmO ziZXwW-+Vou>0Kt@jF$2lwXZZ6!jV5}#_8|}K+v&xGSZ4cx~W^_Kkb>nKQ8t22iNRH zp~^RZjzN7r+EiLc%867sM!GITK1zBFGG!~WNP*6<0#|~#+EA{!BVu>C=EvIXMbe5k ze-%gj1P^%FfflIyroqvLC`IX0Fl8NZX@iW0)3LN^_BpdQaI5ixHt&g z*lMMZrpbBkzOYqpRn?uJ(W$`O(VXrRmP=MtO%-j^pvCU89K9=73v0TZ$J80@F3L?D JxBnQu`!^~Ht%(2t delta 5412 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 O;{Ok=nBQzCZU6uh^(SBe diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/lodash.memoize.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/lodash.memoize.bin new file mode 100644 index 0000000000..a06fad7380 --- /dev/null +++ b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/lodash.memoize.bin @@ -0,0 +1,21 @@ +HTTP/1.1 200 OK +Date: Mon, 11 Dec 2017 18:38:52 GMT +Content-Type: application/vnd.npm.install-v1+json +Content-Length: 5904 +Connection: keep-alive +Set-Cookie: __cfduid=d942f2b24f634f142722f0777b300562a1513017532; expires=Tue, 11-Dec-18 18:38:52 GMT; path=/; domain=.yarnpkg.com; HttpOnly +Cache-Control: max-age=300 +Last-Modified: Mon, 22 May 2017 3:50:12 GMT +ETag: "59225ff4-1710" +Accept-Ranges: bytes +Via: 1.1 varnish +Age: 3081 +X-Served-By: cache-mdw17327-MDW +X-Cache: HIT +X-Cache-Hits: 1 +X-Timer: S1513017532.081757,VS0,VE1 +Vary: Accept-Encoding, Accept +Server: cloudflare-nginx +CF-RAY: 3cba90377a832591-ORD + +{"versions":{"2.0.0":{"name":"lodash.memoize","version":"2.0.0","dependencies":{"lodash.isfunction":"~2.0.0","lodash._keyprefix":"~2.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"dbd81ea8b64e05d3dfd43ad9a249ceeec51a3c56","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-2.0.0.tgz"}},"2.1.0":{"name":"lodash.memoize","version":"2.1.0","dependencies":{"lodash.isfunction":"~2.1.0","lodash._keyprefix":"~2.1.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"81b0d5d070402321ae6350ef36e61d436963f78b","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-2.1.0.tgz"}},"2.2.0":{"name":"lodash.memoize","version":"2.2.0","dependencies":{"lodash.isfunction":"~2.2.0","lodash._keyprefix":"~2.2.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"25e24314b2321bc8ee6b375634378e1dadb8b500","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-2.2.0.tgz"}},"2.2.1":{"name":"lodash.memoize","version":"2.2.1","dependencies":{"lodash.isfunction":"~2.2.1","lodash._keyprefix":"~2.2.1"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"7ada90bea3cb07b08ed3e1a3b8366b630d7e47c4","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-2.2.1.tgz"}},"2.3.0":{"name":"lodash.memoize","version":"2.3.0","dependencies":{"lodash.isfunction":"~2.3.0","lodash._keyprefix":"~2.3.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"33e069f7c8aecd62740354308507eccc0177c9f7","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-2.3.0.tgz"}},"2.4.0":{"name":"lodash.memoize","version":"2.4.0","dependencies":{"lodash.isfunction":"~2.4.0","lodash._keyprefix":"~2.4.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"abf14070c8382fd1b25d26e7817727ff5557c0d2","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-2.4.0.tgz"}},"2.4.1":{"name":"lodash.memoize","version":"2.4.1","dependencies":{"lodash.isfunction":"~2.4.1","lodash._keyprefix":"~2.4.1"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"a014470dd6d03e73663843ea3b60d6972c3b8c30","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-2.4.1.tgz"}},"3.0.0":{"name":"lodash.memoize","version":"3.0.0","dependencies":{"lodash.isfunction":"^3.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"ff7475e87866d7a8d556d615ea8a8b9b6af9e6c4","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.0.tgz"}},"3.0.1":{"name":"lodash.memoize","version":"3.0.1","dependencies":{"lodash.isfunction":"^3.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"ec9f7c48ec76405a9d0ab21111c1408a9c5f9bdd","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.1.tgz"}},"3.0.2":{"name":"lodash.memoize","version":"3.0.2","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"7b7ce2816a8c9d6f3beb21caa0985d3de2ea3e86","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.2.tgz"}},"3.0.3":{"name":"lodash.memoize","version":"3.0.3","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2fc47e23b9edf8a9c8f23298452240350c3b196d","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.3.tgz"}},"3.0.4":{"name":"lodash.memoize","version":"3.0.4","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"2dcbd2c287cbc0a55cc42328bd0c736150d53e3f","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz"}},"3.1.0":{"name":"lodash.memoize","version":"3.1.0","dependencies":{"lodash._mapcache":"^3.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"63b2914fd54205b58144037060812edc12040edf","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.1.0.tgz"}},"3.1.1":{"name":"lodash.memoize","version":"3.1.1","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"581bc0bf46e3d5dcde7b305cbd7121926ff0d84c","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.1.1.tgz"}},"4.0.0":{"name":"lodash.memoize","version":"4.0.0","dependencies":{"lodash._mapcache":"^4.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"9f65275a01ad2eb97722315621175bf0f99f725b","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.0.0.tgz"}},"4.0.1":{"name":"lodash.memoize","version":"4.0.1","dependencies":{"lodash._mapcache":"^4.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"f510e66c098e431a7656b1f9456c1402d880a46a","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.0.1.tgz"}},"4.0.2":{"name":"lodash.memoize","version":"4.0.2","dependencies":{"lodash._mapcache":"~4.1.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"7e205ba23f6a6b1c55e541ebdf919bc0d5bcde1d","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.0.2.tgz"}},"4.0.3":{"name":"lodash.memoize","version":"4.0.3","dependencies":{"lodash._mapcache":"~4.1.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"ec33633118d0931dd143d0480b1aae9397c9f572","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.0.3.tgz"}},"4.1.0":{"name":"lodash.memoize","version":"4.1.0","dependencies":{"lodash._root":"~3.0.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"7b29100f5ee714466528e09bd5da4fb2898524c1","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.0.tgz"}},"4.1.1":{"name":"lodash.memoize","version":"4.1.1","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1f5a26e0560c7eed6140c4f4fb56be248456c8a1","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.1.tgz"}},"4.1.2":{"name":"lodash.memoize","version":"4.1.2","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"bcc6c49a42a2840ed997f323eada5ecd182e0bfe","tarball":"https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz"}}},"name":"lodash.memoize","dist-tags":{"latest":"4.1.2"},"modified":"2017-05-22T03:50:12.401Z"} \ No newline at end of file diff --git a/__tests__/fixtures/why/dep-included-at-2-levels/b/package.json b/__tests__/fixtures/why/dep-included-at-2-levels/b/package.json new file mode 100644 index 0000000000..fc5061589d --- /dev/null +++ b/__tests__/fixtures/why/dep-included-at-2-levels/b/package.json @@ -0,0 +1,8 @@ +{ + "name": "b", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "caniuse-api": "^2.0.0" + } +} diff --git a/__tests__/fixtures/why/dep-included-at-2-levels/package.json b/__tests__/fixtures/why/dep-included-at-2-levels/package.json new file mode 100644 index 0000000000..190b600fc8 --- /dev/null +++ b/__tests__/fixtures/why/dep-included-at-2-levels/package.json @@ -0,0 +1,9 @@ +{ + "name": "a", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "b": "file:./b", + "caniuse-lite": "^1.0.0" + } +} diff --git a/src/cli/commands/why.js b/src/cli/commands/why.js index 3ef50b145f..73a6ff82d4 100644 --- a/src/cli/commands/why.js +++ b/src/cli/commands/why.js @@ -160,7 +160,7 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg const matchRef = matchInfo.pkg._reference; invariant(matchRef, 'expected reference'); - const matchPatterns = matchRef.patterns; + const distinctMatchPatterns = new Set(matchRef.patterns); const matchRequests = matchRef.requests; const reasons = []; @@ -192,7 +192,7 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg // reason: exists in manifest let rootType; - for (const pattern of matchPatterns) { + for (const pattern of distinctMatchPatterns) { rootType = install.rootPatternsToOrigin[pattern]; if (rootType) { reasons.push({ diff --git a/src/package-request.js b/src/package-request.js index 25a1bbd0ac..3f6f747b6a 100644 --- a/src/package-request.js +++ b/src/package-request.js @@ -39,8 +39,10 @@ export default class PackageRequest { this.pattern = req.pattern; this.config = resolver.config; this.foundInfo = null; + } - resolver.usedRegistries.add(req.registry); + init() { + this.resolver.usedRegistries.add(this.registry); } parentRequest: ?PackageRequest; diff --git a/src/package-resolver.js b/src/package-resolver.js index 19b7f92e4e..65fdccfb26 100644 --- a/src/package-resolver.js +++ b/src/package-resolver.js @@ -490,33 +490,36 @@ export default class PackageResolver { return; } + const request = new PackageRequest(req, this); const fetchKey = `${req.registry}:${req.pattern}:${String(req.optional)}`; - if (this.fetchingPatterns.has(fetchKey)) { - return; - } - this.fetchingPatterns.add(fetchKey); + const initialFetch = !this.fetchingPatterns.has(fetchKey); + let fresh = false; if (this.activity) { this.activity.tick(req.pattern); } - const lockfileEntry = this.lockfile.getLocked(req.pattern); - let fresh = false; + if (initialFetch) { + this.fetchingPatterns.add(fetchKey); - if (lockfileEntry) { - const {range, hasVersion} = normalizePattern(req.pattern); + const lockfileEntry = this.lockfile.getLocked(req.pattern); - if (this.isLockfileEntryOutdated(lockfileEntry.version, range, hasVersion)) { - this.reporter.warn(this.reporter.lang('incorrectLockfileEntry', req.pattern)); - this.removePattern(req.pattern); - this.lockfile.removePattern(req.pattern); + if (lockfileEntry) { + const {range, hasVersion} = normalizePattern(req.pattern); + + if (this.isLockfileEntryOutdated(lockfileEntry.version, range, hasVersion)) { + this.reporter.warn(this.reporter.lang('incorrectLockfileEntry', req.pattern)); + this.removePattern(req.pattern); + this.lockfile.removePattern(req.pattern); + fresh = true; + } + } else { fresh = true; } - } else { - fresh = true; + + request.init(); } - const request = new PackageRequest(req, this); await request.find({fresh, frozen: this.frozen}); } diff --git a/src/reporters/buffer-reporter.js b/src/reporters/buffer-reporter.js index d0271790c9..09a10f9c22 100644 --- a/src/reporters/buffer-reporter.js +++ b/src/reporters/buffer-reporter.js @@ -4,7 +4,7 @@ import JSONReporter from './json-reporter.js'; type Buffer = Array<{ type: string, - data: string | Object | number, + data: Object, error: boolean, }>; From 4924d7030de387e03bffeb9d475ac07711601865 Mon Sep 17 00:00:00 2001 From: Bartosz Kaszubowski Date: Mon, 15 Jan 2018 14:47:14 +0100 Subject: [PATCH 20/34] chore(package): move devDeps to appropriate place (#5166) --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 0836a2192d..b89cf0925c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "preferGlobal": true, "description": "📦🐈 Fast, reliable, and secure dependency management.", "dependencies": { - "babel-eslint": "^7.2.3", "babel-runtime": "^6.26.0", "bytes": "^2.4.0", "camelcase": "^4.0.0", @@ -17,9 +16,6 @@ "debug": "^2.2.0", "detect-indent": "^5.0.0", "dnscache": "^1.0.1", - "eslint-plugin-jest": "^20.0.3", - "eslint-plugin-jsx-a11y": "^6.0.2", - "eslint-plugin-relay": "^0.0.8", "glob": "^7.1.1", "gunzip-maybe": "^1.4.0", "ini": "^1.3.4", @@ -53,6 +49,7 @@ }, "devDependencies": { "babel-core": "^6.26.0", + "babel-eslint": "^7.2.3", "babel-loader": "^6.2.5", "babel-plugin-array-includes": "^2.0.3", "babel-plugin-transform-inline-imports-commonjs": "^1.0.0", @@ -68,9 +65,12 @@ "eslint-plugin-babel": "^4.0.0", "eslint-plugin-flowtype": "^2.35.0", "eslint-plugin-jasmine": "^2.6.2", + "eslint-plugin-jest": "^20.0.3", + "eslint-plugin-jsx-a11y": "^6.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", "eslint-plugin-prettier": "^2.1.2", "eslint-plugin-react": "^7.1.0", + "eslint-plugin-relay": "^0.0.8", "eslint-plugin-yarn-internal": "file:scripts/eslint-rules", "execa": "^0.7.0", "flow-bin": "^0.52.0", From dc7057688fd0e8a60653b99bf7a78939a35d7fb4 Mon Sep 17 00:00:00 2001 From: Karolis Narkevicius Date: Mon, 15 Jan 2018 16:00:21 +0000 Subject: [PATCH 21/34] fix(auth): Fixes authentication conditions and logic with registries (#5216) * Add more thorough tests for registries.npm.request authorisation * Fix the bug where npm private packages where not authed correctly * Remove the old tests that have now been compacted into test gen * Clarify the naming of the request url check * Alternative approach for supporting registries with multiple paths * Improve the naming and order of the test suites * Clarify the registry request test suite names further --- __tests__/registries/npm-registry.js | 617 +++++++++++++++++++++------ src/registries/npm-registry.js | 49 ++- 2 files changed, 530 insertions(+), 136 deletions(-) diff --git a/__tests__/registries/npm-registry.js b/__tests__/registries/npm-registry.js index 6fa85aac66..ce0f97e464 100644 --- a/__tests__/registries/npm-registry.js +++ b/__tests__/registries/npm-registry.js @@ -72,138 +72,504 @@ function createMocks(): Object { } describe('request', () => { - test('should call requestManager.request with url', () => { + // a helper function for creating an instance of npm registry, + // making requests and inspecting request parameters + function createRegistry(config: Object): Object { const testCwd = '.'; const {mockRequestManager, mockRegistries, mockReporter} = createMocks(); const npmRegistry = new NpmRegistry(testCwd, mockRegistries, mockRequestManager, mockReporter); + npmRegistry.config = config; + return { + request(url: string, options: Object, packageName: string): Object { + npmRegistry.request(url, options, packageName); + const lastIndex = mockRequestManager.request.mock.calls.length - 1; + const requestParams = mockRequestManager.request.mock.calls[lastIndex][0]; + return requestParams; + }, + }; + } + test('should call requestManager.request with url', () => { const url = 'https://github.com/yarnpkg/yarn.tgz'; - - npmRegistry.request(url); - - const requestParams = mockRequestManager.request.mock.calls[0][0]; - + const config = {}; + const requestParams = createRegistry(config).request(url); expect(requestParams.url).toBe(url); }); - test('should not add authorization header if pathname not to registry', () => { - const testCwd = '.'; - const {mockRequestManager, mockRegistries, mockReporter} = createMocks(); - const npmRegistry = new NpmRegistry(testCwd, mockRegistries, mockRequestManager, mockReporter); - - const url = 'https://github.com/yarnpkg/yarn.tgz'; - - npmRegistry.request(url); - - const requestParams = mockRequestManager.request.mock.calls[0][0]; - - expect(requestParams.headers.authorization).toBeUndefined(); - }); - - test('should not add authorization header if pathname not to registry and always-auth is true', () => { - const testCwd = '.'; - const {mockRequestManager, mockRegistries, mockReporter} = createMocks(); - const npmRegistry = new NpmRegistry(testCwd, mockRegistries, mockRequestManager, mockReporter); - - const url = 'https://github.com/yarnpkg/yarn.tgz'; - - npmRegistry.config = { - 'always-auth': true, - _authToken: 'testAuthToken', - }; - npmRegistry.request(url); - - const requestParams = mockRequestManager.request.mock.calls[0][0]; - - expect(requestParams.headers.authorization).toBeUndefined(); - }); - - test('should not add authorization header if pathname is to registry and always-auth is false', () => { - const testCwd = '.'; - const {mockRequestManager, mockRegistries, mockReporter} = createMocks(); - const npmRegistry = new NpmRegistry(testCwd, mockRegistries, mockRequestManager, mockReporter); - - const url = 'https://registry.npmjs.org/yarnpkg/yarn.tgz'; - - npmRegistry.config = { - // Default is: 'always-auth': false, - _authToken: 'testAuthToken', - }; - npmRegistry.request(url); - - const requestParams = mockRequestManager.request.mock.calls[0][0]; - - expect(requestParams.headers.authorization).toBeUndefined(); - }); - - test('should not add authorization header if pathname is to registry and not scopped package', () => { - const testCwd = '.'; - const {mockRequestManager, mockRegistries, mockReporter} = createMocks(); - const npmRegistry = new NpmRegistry(testCwd, mockRegistries, mockRequestManager, mockReporter); - - const url = 'https://registry.npmjs.org/yarnpkg/yarn.tgz'; - - npmRegistry.config = { - _authToken: 'testAuthToken', - }; - npmRegistry.request(url); - - const requestParams = mockRequestManager.request.mock.calls[0][0]; - - expect(requestParams.headers.authorization).toBeUndefined(); - }); - - test('should add authorization header if pathname is to registry and always-auth is true', () => { - const testCwd = '.'; - const {mockRequestManager, mockRegistries, mockReporter} = createMocks(); - const npmRegistry = new NpmRegistry(testCwd, mockRegistries, mockRequestManager, mockReporter); - - const url = 'https://registry.npmjs.org/yarnpkg/yarn.tgz'; - - npmRegistry.config = { - 'always-auth': true, - _authToken: 'testAuthToken', - }; - npmRegistry.request(url); - - const requestParams = mockRequestManager.request.mock.calls[0][0]; - - expect(requestParams.headers.authorization).toBe('Bearer testAuthToken'); - }); - - test('should add authorization header if pathname is to registry and is scopped package', () => { - const testCwd = '.'; - const {mockRequestManager, mockRegistries, mockReporter} = createMocks(); - const npmRegistry = new NpmRegistry(testCwd, mockRegistries, mockRequestManager, mockReporter); - - const url = 'https://registry.npmjs.org/@testScope%2fyarn.tgz'; - - npmRegistry.config = { - _authToken: 'testAuthToken', - }; - npmRegistry.request(url); - - const requestParams = mockRequestManager.request.mock.calls[0][0]; - - expect(requestParams.headers.authorization).toBe('Bearer testAuthToken'); - }); - - test('should add authorization header with token for custom registries with a scoped package', () => { - const testCwd = '.'; - const {mockRequestManager, mockRegistries, mockReporter} = createMocks(); - const npmRegistry = new NpmRegistry(testCwd, mockRegistries, mockRequestManager, mockReporter); - - const url = 'https://some.other.registry/@testScope%2fyarn.tgz'; - - npmRegistry.config = { - '//some.other.registry/:_authToken': 'testScopedAuthToken', - '@testScope:registry': '//some.other.registry/', - }; - npmRegistry.request(url); - - const requestParams = mockRequestManager.request.mock.calls[0][0]; - - expect(requestParams.headers.authorization).toBe('Bearer testScopedAuthToken'); + const testCases = [ + { + title: 'using npm as default registry and using private registry for scoped packages', + config: { + '//registry.myorg.com/:_authToken': 'scopedPrivateAuthToken', + '@private:registry': 'https://registry.myorg.com/', + }, + requests: [ + { + url: 'yarn', + pkg: 'yarn', + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: '@yarn%2fcore', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: '-/package/yarn/dist-tags', + pkg: 'yarn', + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: '-/package/@yarn%2fcore/dist-tags', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: '-/user/token/abcdef', + pkg: null, + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: 'https://registry.npmjs.org/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.yarnpkg.com', auth: false}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: null, + expect: {root: 'https://registry.yarnpkg.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: '@yarn/core', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: '@private/pkg', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com', auth: 'scopedPrivateAuthToken'}, + }, + { + url: 'https://some.cdn.com/some-hash/@private-pkg-1.0.0.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@private/pkg', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + ], + }, + { + title: 'using scoped packages in both npm and private registry', + config: { + '//registry.npmjs.org/:_authToken': 'scopedNpmAuthToken', + '@yarn:registry': 'https://registry.npmjs.org/', + '//registry.myorg.com/:_authToken': 'scopedPrivateAuthToken', + '@private:registry': 'https://registry.myorg.com/', + }, + requests: [ + { + url: 'yarn', + pkg: 'yarn', + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: '@yarn%2fcore', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'scopedNpmAuthToken'}, + }, + { + url: '-/package/yarn/dist-tags', + pkg: 'yarn', + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: '-/package/@yarn%2fcore/dist-tags', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'scopedNpmAuthToken'}, + }, + { + url: '-/user/token/abcdef', + pkg: null, + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: 'https://registry.npmjs.org/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'scopedNpmAuthToken'}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.yarnpkg.com', auth: 'scopedNpmAuthToken'}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: null, + expect: {root: 'https://registry.yarnpkg.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: '@yarn/core', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: '@private/pkg', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com', auth: 'scopedPrivateAuthToken'}, + }, + { + url: 'https://some.cdn.com/some-hash/@private-pkg-1.0.0.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@private/pkg', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + ], + }, + { + title: 'using authenticated npm and using private registry for scoped packages', + config: { + _authToken: 'scopedNpmAuthToken', + '//registry.myorg.com/:_authToken': 'scopedPrivateAuthToken', + '@private:registry': 'https://registry.myorg.com/', + }, + requests: [ + { + url: 'yarn', + pkg: 'yarn', + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: '@yarn%2fcore', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'scopedNpmAuthToken'}, + }, + { + url: '-/package/yarn/dist-tags', + pkg: 'yarn', + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: '-/package/@yarn%2fcore/dist-tags', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'scopedNpmAuthToken'}, + }, + { + url: '-/user/token/abcdef', + pkg: null, + expect: {root: 'https://registry.npmjs.org', auth: false}, + }, + { + url: 'https://registry.npmjs.org/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'scopedNpmAuthToken'}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.yarnpkg.com', auth: 'scopedNpmAuthToken'}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: null, + expect: {root: 'https://registry.yarnpkg.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: '@yarn/core', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: '@private/pkg', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com', auth: 'scopedPrivateAuthToken'}, + }, + { + url: 'https://some.cdn.com/some-hash/@private-pkg-1.0.0.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@private/pkg', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + ], + }, + { + title: 'using npm with always-auth and using private registry for scoped packages', + config: { + 'always-auth': true, + '//registry.npmjs.org/:_authToken': 'npmAuthToken', + '@private:registry': 'https://registry.myorg.com/', + '//registry.myorg.com/:_authToken': 'scopedPrivateAuthToken', + }, + requests: [ + { + url: 'yarn', + pkg: 'yarn', + expect: {root: 'https://registry.npmjs.org', auth: 'npmAuthToken'}, + }, + { + url: '@yarn%2fcore', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'npmAuthToken'}, + }, + { + url: '-/package/yarn/dist-tags', + pkg: 'yarn', + expect: {root: 'https://registry.npmjs.org', auth: 'npmAuthToken'}, + }, + { + url: '-/package/@yarn%2fcore/dist-tags', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'npmAuthToken'}, + }, + { + url: '-/user/token/abcdef', + pkg: null, + expect: {root: 'https://registry.npmjs.org', auth: 'npmAuthToken'}, + }, + { + url: 'https://registry.npmjs.org/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'npmAuthToken'}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.yarnpkg.com', auth: 'npmAuthToken'}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: null, + expect: {root: 'https://registry.yarnpkg.com', auth: 'npmAuthToken'}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: '@yarn/core', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: '@private/pkg', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com', auth: 'scopedPrivateAuthToken'}, + }, + { + url: 'https://some.cdn.com/some-hash/@private-pkg-1.0.0.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@private/pkg', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + ], + }, + { + title: 'using private registry as default registry and using scoped packages on npm registry', + config: { + 'always-auth': true, + registry: 'https://registry.myorg.com/', + '//registry.myorg.com/:_authToken': 'privateAuthToken', + '//registry.npmjs.org/:_authToken': 'scopedNpmAuthToken', + '@yarn:registry': 'https://registry.npmjs.org/', + }, + requests: [ + { + url: 'yarn', + pkg: 'yarn', + expect: {root: 'https://registry.myorg.com', auth: 'privateAuthToken'}, + }, + { + url: '@yarn%2fcore', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'scopedNpmAuthToken'}, + }, + { + url: '-/package/yarn/dist-tags', + pkg: 'yarn', + expect: {root: 'https://registry.myorg.com', auth: 'privateAuthToken'}, + }, + { + url: '-/package/@yarn%2fcore/dist-tags', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'scopedNpmAuthToken'}, + }, + { + url: '-/user/token/abcdef', + pkg: null, + expect: {root: 'https://registry.myorg.com', auth: 'privateAuthToken'}, + }, + { + url: 'https://registry.npmjs.org/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.npmjs.org', auth: 'scopedNpmAuthToken'}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: '@yarn/core', + expect: {root: 'https://registry.yarnpkg.com', auth: 'scopedNpmAuthToken'}, + }, + { + url: 'https://registry.yarnpkg.com/dist/-/@yarn-core-1.0.0.tgz', + pkg: null, + expect: {root: 'https://registry.yarnpkg.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: '@yarn/core', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@yarn/core.tgz', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: '@private/pkg', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com', auth: 'privateAuthToken'}, + }, + { + url: 'https://some.cdn.com/some-hash/@private-pkg-1.0.0.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@private/pkg', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + ], + }, + { + title: 'registry url and request url path sensitivity', + config: { + '@private:registry': 'https://registry.myorg.com/api/npm/registry/', + '//registry.myorg.com/api/npm/registry/:_authToken': 'scopedPrivateAuthToken', + }, + requests: [ + { + url: 'https://registry.myorg.com/api/npm/registry/private---pkg.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com/api/npm/registry/', auth: 'scopedPrivateAuthToken'}, + }, + { + url: 'https://registry.myorg.com/api/packages/private---pkg.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com/api/packages/', auth: false}, + }, + ], + }, + { + title: 'using custom-host-suffix for registries where pathnames play a role', + config: { + '@private:registry': 'https://registry.myorg.com/api/npm/registry/', + '//registry.myorg.com/api/npm/registry/:_authToken': 'scopedPrivateAuthToken', + 'custom-host-suffix': 'registry.myorg.com', + }, + requests: [ + { + url: '@private/pkg', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com/api/npm/registry/', auth: 'scopedPrivateAuthToken'}, + }, + { + url: 'https://some.cdn.com/some-hash/@private-pkg-1.0.0.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@private/pkg', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://registry.myorg.com/api/packages/private---pkg.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com/api/packages/', auth: 'scopedPrivateAuthToken'}, + }, + ], + }, + { + title: 'using multiple config entries for registries where pathnames play a role', + config: { + '@private:registry': 'https://registry.myorg.com/api/npm/registry/', + '//registry.myorg.com/api/npm/registry/:_authToken': 'scopedPrivateAuthToken', + '//registry.myorg.com/api/packages/:_authToken': 'scopedPrivateAuthToken', + }, + requests: [ + { + url: '@private/pkg', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com/api/npm/registry/', auth: 'scopedPrivateAuthToken'}, + }, + { + url: 'https://some.cdn.com/some-hash/@private-pkg-1.0.0.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://some.cdn.com/@private/pkg', + pkg: null, + expect: {root: 'https://some.cdn.com', auth: false}, + }, + { + url: 'https://registry.myorg.com/api/packages/private---pkg.tar.gz', + pkg: '@private/pkg', + expect: {root: 'https://registry.myorg.com/api/packages/', auth: 'scopedPrivateAuthToken'}, + }, + ], + }, + ]; + + testCases.forEach(testCase => { + describe(testCase.title, () => { + const registry = createRegistry(testCase.config); + testCase.requests.forEach(req => { + const desc = + `with request url ${req.url}${req.pkg ? ` in context of package ${req.pkg}` : ''} ` + + `auth is ${req.expect.auth ? req.expect.auth : 'not sent'}`; + (req.skip ? it.skip : req.only ? it.only : it)(desc, () => { + const requestParams = registry.request(req.url, {}, req.pkg); + expect(requestParams.url.substr(0, req.expect.root.length)).toBe(req.expect.root); + expect(requestParams.headers.authorization).toBe(req.expect.auth ? `Bearer ${req.expect.auth}` : undefined); + }); + }); + }); }); }); @@ -222,6 +588,9 @@ describe('isRequestToRegistry functional test', () => { ['http://foo.bar/foo/bar/baz', 'https://foo.bar:443/foo/'], ['https://foo.bar/foo/bar/baz', 'https://foo.bar:443/foo/'], ['HTTP://xn--xample-hva.com:80/foo/bar/baz', 'http://êxample.com/foo/bar/baz'], + // yarn and npm registries are interchangeable + ['https://registry.npmjs.org/foo/bar', 'https://registry.npmjs.org/'], + ['https://registry.yarnpkg.com/foo/bar', 'https://registry.npmjs.org/'], ]; const invalidRegistryUrls = [ diff --git a/src/registries/npm-registry.js b/src/registries/npm-registry.js index 501ef18a48..3a553d1131 100644 --- a/src/registries/npm-registry.js +++ b/src/registries/npm-registry.js @@ -72,6 +72,19 @@ function normalizePath(val: mixed): ?string { return resolveWithHome(val); } +type UrlParts = { + host: string, + path: string, +}; + +function urlParts(requestUrl: string): UrlParts { + const normalizedUrl = normalizeUrl(requestUrl); + const parsed = url.parse(normalizedUrl); + const host = parsed.host || ''; + const path = parsed.path || ''; + return {host, path}; +} + export default class NpmRegistry extends Registry { constructor(cwd: string, registries: ConfigRegistries, requestManager: RequestManager, reporter: Reporter) { super(cwd, registries, requestManager, reporter); @@ -100,21 +113,18 @@ export default class NpmRegistry extends Registry { } isRequestToRegistry(requestUrl: string, registryUrl: string): boolean { - const normalizedRequestUrl = normalizeUrl(requestUrl); - const normalizedRegistryUrl = normalizeUrl(registryUrl); - const requestParsed = url.parse(normalizedRequestUrl); - const registryParsed = url.parse(normalizedRegistryUrl); - const requestHost = requestParsed.host || ''; - const registryHost = registryParsed.host || ''; - const requestPath = requestParsed.path || ''; - const registryPath = registryParsed.path || ''; + const request = urlParts(requestUrl); + const registry = urlParts(registryUrl); const customHostSuffix = this.getRegistryOrGlobalOption(registryUrl, 'custom-host-suffix'); + const requestToRegistryHost = () => request.host === registry.host; + const requestToYarn = () => YARN_REGISTRY.includes(request.host) && DEFAULT_REGISTRY.includes(registry.host); + return ( - requestHost === registryHost && - (requestPath.startsWith(registryPath) || + (requestToRegistryHost() || requestToYarn()) && + (request.path.startsWith(registry.path) || // For some registries, the package path does not prefix with the registry path - (typeof customHostSuffix === 'string' && requestHost.endsWith(customHostSuffix))) + (typeof customHostSuffix === 'string' && request.host.endsWith(customHostSuffix))) ); } @@ -133,7 +143,7 @@ export default class NpmRegistry extends Registry { opts.headers, ); - const isToRegistry = this.isRequestToRegistry(requestUrl, registry); + const isToRegistry = this.isRequestToRegistry(requestUrl, registry) || this.requestNeedsAuth(requestUrl); // this.token must be checked to account for publish requests on non-scopped packages if (this.token || (isToRegistry && (alwaysAuth || this.isScopedPackage(packageIdent)))) { @@ -156,6 +166,21 @@ export default class NpmRegistry extends Registry { }); } + requestNeedsAuth(requestUrl: string): boolean { + const config = this.config; + const requestParts = urlParts(requestUrl); + return !!Object.keys(config).find(option => { + const parts = option.split(':'); + if (parts.length === 2 && parts[1] === '_authToken') { + const registryParts = urlParts(parts[0]); + if (requestParts.host === registryParts.host && requestParts.path.startsWith(registryParts.path)) { + return true; + } + } + return false; + }); + } + async checkOutdated(config: Config, name: string, range: string): CheckOutdatedReturn { const req = await this.request(NpmRegistry.escapeName(name), { headers: {Accept: 'application/json'}, From 7ed01cfb2b29b59d9b97601ff5e342bd58f53224 Mon Sep 17 00:00:00 2001 From: Jeff Valore Date: Mon, 15 Jan 2018 11:39:23 -0500 Subject: [PATCH 22/34] Fix transient symlinks overriding direct ones v2 (#5016) * Add test for bug with conflicting bin link names If a transient dependency has a bin link with the same name as a direct dependency, sometimes the top level bin link with lead to the transient dependency rather than the direct one after install. This test asserts that bin links from direct dependencies are installed. * Do not overwrite existing bin links The bin links are created in two passes during install. In the first pass all direct dependencies for the installing module and transient dependencies are created in their respective bin directories. In the second pass top level bin links are created for all modules, including transient dependencies. This patch makes sure the second pass doesn't overwrite links from the first pass which fixes a problem where links from transient dependencies could overwrite links from direct dependencies. * rename a test package to cause a test to fail. implement different fix for bin link ordering. * change determineTopLevelBinLinkOrder method return type to be more obvious * address PR comments --- __tests__/commands/install/bin-links.js | 11 ++++++++ .../a-dep/bin | 2 ++ .../a-dep/c-dep/bin | 2 ++ .../a-dep/c-dep/package.json | 7 +++++ .../a-dep/package.json | 10 +++++++ .../f-dep/bin | 2 ++ .../f-dep/d-dep/bin | 2 ++ .../f-dep/d-dep/package.json | 7 +++++ .../f-dep/package.json | 10 +++++++ .../package.json | 6 +++++ src/package-linker.js | 27 ++++++++++++++----- 11 files changed, 80 insertions(+), 6 deletions(-) create mode 100755 __tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/bin create mode 100755 __tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/c-dep/bin create mode 100644 __tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/c-dep/package.json create mode 100644 __tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/package.json create mode 100755 __tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/bin create mode 100755 __tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/d-dep/bin create mode 100644 __tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/d-dep/package.json create mode 100644 __tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/package.json create mode 100644 __tests__/fixtures/install/install-bin-links-conflicting-names/package.json diff --git a/__tests__/commands/install/bin-links.js b/__tests__/commands/install/bin-links.js index 3e78a5c4ab..59208a058d 100644 --- a/__tests__/commands/install/bin-links.js +++ b/__tests__/commands/install/bin-links.js @@ -145,6 +145,17 @@ test('first dep is installed when same level and reference count and one is a de }); }); +// Scenario: Transitive dependency having bin link with a name that's conflicting with that of a direct dependency. +// Behavior: a-dep and b-dep is linked in node_modules/.bin rather than c-dep and d-dep +test('direct dependency is linked when bin name conflicts with transitive dependency', (): Promise => { + return runInstall({binLinks: true}, 'install-bin-links-conflicting-names', async config => { + const stdout1 = await execCommand(config.cwd, ['node_modules', '.bin', 'binlink1'], []); + const stdout2 = await execCommand(config.cwd, ['node_modules', '.bin', 'binlink2'], []); + expect(stdout1[0]).toEqual('direct a-dep'); + expect(stdout2[0]).toEqual('direct f-dep'); + }); +}); + // fixes https://github.com/yarnpkg/yarn/issues/3535 // quite a heavy test, did not find a way to isolate test('Only top level (after hoisting) bin links should be linked', (): Promise => { diff --git a/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/bin b/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/bin new file mode 100755 index 0000000000..d993532d9a --- /dev/null +++ b/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/bin @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log('direct a-dep'); diff --git a/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/c-dep/bin b/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/c-dep/bin new file mode 100755 index 0000000000..3953becac0 --- /dev/null +++ b/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/c-dep/bin @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log('transient c-dep'); diff --git a/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/c-dep/package.json b/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/c-dep/package.json new file mode 100644 index 0000000000..f0b4669749 --- /dev/null +++ b/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/c-dep/package.json @@ -0,0 +1,7 @@ +{ + "name": "c-dep", + "version": "0.0.1", + "bin": { + "binlink2": "./bin" + } +} diff --git a/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/package.json b/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/package.json new file mode 100644 index 0000000000..6be8db4d09 --- /dev/null +++ b/__tests__/fixtures/install/install-bin-links-conflicting-names/a-dep/package.json @@ -0,0 +1,10 @@ +{ + "name": "a-dep", + "version": "0.0.1", + "bin": { + "binlink1": "./bin" + }, + "dependencies": { + "c-dep": "file:c-dep" + } +} diff --git a/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/bin b/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/bin new file mode 100755 index 0000000000..526ad3e3f2 --- /dev/null +++ b/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/bin @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log('direct f-dep'); diff --git a/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/d-dep/bin b/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/d-dep/bin new file mode 100755 index 0000000000..856f0d437a --- /dev/null +++ b/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/d-dep/bin @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log('transient d-dep'); diff --git a/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/d-dep/package.json b/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/d-dep/package.json new file mode 100644 index 0000000000..725f563fea --- /dev/null +++ b/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/d-dep/package.json @@ -0,0 +1,7 @@ +{ + "name": "d-dep", + "version": "0.0.1", + "bin": { + "binlink1": "./bin" + } +} diff --git a/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/package.json b/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/package.json new file mode 100644 index 0000000000..16c62e620f --- /dev/null +++ b/__tests__/fixtures/install/install-bin-links-conflicting-names/f-dep/package.json @@ -0,0 +1,10 @@ +{ + "name": "b-dep", + "version": "0.0.1", + "bin": { + "binlink2": "./bin" + }, + "dependencies": { + "d-dep": "file:d-dep" + } +} diff --git a/__tests__/fixtures/install/install-bin-links-conflicting-names/package.json b/__tests__/fixtures/install/install-bin-links-conflicting-names/package.json new file mode 100644 index 0000000000..4862ab982b --- /dev/null +++ b/__tests__/fixtures/install/install-bin-links-conflicting-names/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "a-dep": "file:a-dep", + "f-dep": "file:f-dep" + } +} diff --git a/src/package-linker.js b/src/package-linker.js index e32fc2480c..31236c36e2 100644 --- a/src/package-linker.js +++ b/src/package-linker.js @@ -401,7 +401,7 @@ export default class PackageLinker { // create binary links if (this.config.binLinks) { - const topLevelDependencies = this.determineTopLevelBinLinks(flatTree); + const topLevelDependencies = this.determineTopLevelBinLinkOrder(flatTree); const tickBin = this.reporter.progress(flatTree.length + topLevelDependencies.length); // create links in transient dependencies @@ -420,7 +420,7 @@ export default class PackageLinker { // create links at top level for all dependencies. await promise.queue( topLevelDependencies, - async ([dest, pkg]) => { + async ([dest, {pkg}]) => { if (pkg._reference && pkg._reference.location && pkg.bin && Object.keys(pkg.bin).length) { const binLoc = path.join(this.config.lockfileFolder, this.config.getFolder(pkg)); await this.linkSelfDependencies(pkg, dest, binLoc); @@ -436,17 +436,32 @@ export default class PackageLinker { } } - determineTopLevelBinLinks(flatTree: HoistManifestTuples): Array<[string, Manifest]> { + determineTopLevelBinLinkOrder(flatTree: HoistManifestTuples): HoistManifestTuples { const linksToCreate = new Map(); - for (const [dest, {pkg, isDirectRequire}] of flatTree) { + for (const [dest, hoistManifest] of flatTree) { + const {pkg, isDirectRequire} = hoistManifest; const {name} = pkg; if (isDirectRequire || (this.topLevelBinLinking && !linksToCreate.has(name))) { - linksToCreate.set(name, [dest, pkg]); + linksToCreate.set(name, [dest, hoistManifest]); } } - return Array.from(linksToCreate.values()); + // Sort the array so that direct dependencies will be linked last. + // Bin links are overwritten if they already exist, so this will cause direct deps to take precedence. + // If someone finds this to be incorrect later, you could also consider sorting descending by + // `linkToCreate.level` which is the dependency tree depth. Direct deps will have level 0 and transitive + // deps will have level > 0. + const transientBins = []; + const topLevelBins = []; + for (const linkToCreate of Array.from(linksToCreate.values())) { + if (linkToCreate[1].isDirectRequire) { + topLevelBins.push(linkToCreate); + } else { + transientBins.push(linkToCreate); + } + } + return [...transientBins, ...topLevelBins]; } resolvePeerModules() { From 953c501b994062fa22b9813a9b20de186fc744bf Mon Sep 17 00:00:00 2001 From: Christian Moritz Date: Mon, 15 Jan 2018 17:41:26 +0100 Subject: [PATCH 23/34] fix(install): use node-gyp from homebrew npm (#4994) * fix(install): use node-gyp from homebrew npm **Summary** With this yarn will be able to discover and use the node-gyp from the homebrew installed npm on macOS instead of falling back to globally installing node-gyp every time a native addon needs to be compiled from source. Homebrew installs a clean copy of npm inside a libexec folder together with node. Previously yarn didn't look there when trying to locate node-gyp and the globally install node-gyp fallback would be used every time when building native addons with a yarn version from homebrew. This PR adds the libexec path of node-gyp from homebrew to the node-gyp search paths of yarn, making it possible to compile native addons using the homebrew npm provided node-gyp with yarn without relying on this fallback. **Test plan** This can't be tested outside a homebrew environment. A way to manually test this on macOS, by installing a test build of this PR with homebrew and trying to install a native addon with it, is provided in the PR description. * test fix on CI by removing global node-gyp --- .circleci/config.yml | 2 -- src/util/execute-lifecycle-script.js | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8ae1926ed5..0a97ac23ce 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -117,7 +117,6 @@ jobs: command: | brew uninstall --ignore-dependencies node HOMEBREW_NO_AUTO_UPDATE=1 brew install node@8 - yarn global add node-gyp - *attach_workspace - *test_build - *test_run @@ -130,7 +129,6 @@ jobs: brew uninstall --ignore-dependencies node HOMEBREW_NO_AUTO_UPDATE=1 brew install node@6 brew link --force node@6 - yarn global add node-gyp - *attach_workspace - *test_build - *test_run diff --git a/src/util/execute-lifecycle-script.js b/src/util/execute-lifecycle-script.js index 7dde2629cc..bacf91bca7 100644 --- a/src/util/execute-lifecycle-script.js +++ b/src/util/execute-lifecycle-script.js @@ -137,6 +137,10 @@ export async function makeEnv( pathParts.unshift( path.join(path.dirname(process.execPath), '..', 'lib', 'node_modules', 'npm', 'bin', 'node-gyp-bin'), ); + // Include node-gyp version from homebrew managed npm, if available. + pathParts.unshift( + path.join(path.dirname(process.execPath), '..', 'libexec', 'lib', 'node_modules', 'npm', 'bin', 'node-gyp-bin'), + ); // Add global bin folder if it is not present already, as some packages depend // on a globally-installed version of node-gyp. From 139c302fbd2a918cfc52d9caa8bc8e10570465c6 Mon Sep 17 00:00:00 2001 From: Danny Soares Date: Mon, 15 Jan 2018 16:49:34 +0000 Subject: [PATCH 24/34] Show current version, when new version is not supplied on "yarn publish" (#4947) * Resolved issue? * Merge latest master and update snapshots * Revert "Merge latest master and update snapshots" This reverts commit 47c14d8bdc13a5636e259e467e091f79e6ac8303. * Update snapshots * Update snapshot --- src/cli/commands/version.js | 1 + src/reporters/lang/en.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/cli/commands/version.js b/src/cli/commands/version.js index ca7bfd9024..2229be03bb 100644 --- a/src/cli/commands/version.js +++ b/src/cli/commands/version.js @@ -77,6 +77,7 @@ export async function setVersion( newVersion = await reporter.question(reporter.lang('newVersion')); if (!required && !newVersion) { + reporter.info(`${reporter.lang('noVersionOnPublish')}: ${oldVersion}`); return function(): Promise { return Promise.resolve(); }; diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index 13f0416ce6..af1bcba6b9 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -246,6 +246,7 @@ const messages = { invalidSemver: 'Invalid semver version', newVersion: 'New version', currentVersion: 'Current version', + noVersionOnPublish: 'Proceeding with current version', manualVersionResolution: 'Unable to find a suitable version for $0, please choose one by typing one of the numbers below:', From 543f649d355bb5b3b0b56e1c73c6e3ca93a299c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Mon, 15 Jan 2018 17:12:39 +0000 Subject: [PATCH 25/34] 1.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b89cf0925c..743c7bafbb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "yarn", "installationMethod": "unknown", - "version": "1.3.2", + "version": "1.4.0", "license": "BSD-2-Clause", "preferGlobal": true, "description": "📦🐈 Fast, reliable, and secure dependency management.", From 00c4b0f3199c8eb2b6cc23e20d33faddb993f1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Fri, 19 Jan 2018 16:04:19 +0000 Subject: [PATCH 26/34] 1.4.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 743c7bafbb..5f23a7086d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "yarn", "installationMethod": "unknown", - "version": "1.4.0", + "version": "1.4.1", "license": "BSD-2-Clause", "preferGlobal": true, "description": "📦🐈 Fast, reliable, and secure dependency management.", From 4bddb3ac8179199ece9aa237d0f92a79a30827d3 Mon Sep 17 00:00:00 2001 From: ConnectDotz Date: Mon, 29 Jan 2018 00:35:59 +0800 Subject: [PATCH 27/34] nohoist baseline implementation (#4979) * nohoist impl check point - nohoist implementation - 'why' command fixes - 'add' command fixes - tests and test fixtures see [RFC #86](https://github.com/yarnpkg/rfcs/pull/86) for detail * fix not adding devDependencies * add nohoist flag and eligibility check 1. added a new flags 'workspaces-nohoist-experimental' to disable nohoist. 2. added eligibility validation in Config.getWorkspaces, violation will be reported and config be ignored. 3. update test fixtures to add private flag for nohoist tests * revert path separator to '#' for display * pass through private flag in root manifest * fix lint error * addressing @bestander review comments on 1/8 * fix merge conflict * fix merge lint issues * address @arcanis comments * update snapshot after merge * one more snapshot update --- __tests__/commands/add.js | 237 ++++---- .../commands/install/workspaces-install.js | 119 +++- __tests__/commands/why.js | 156 +++++- __tests__/config.js | 183 +++++- .../a/package.json | 7 + .../b-2/package.json | 4 + .../b/package.json | 7 + .../c/package.json | 7 + .../d/package.json | 4 + .../package.json | 8 + .../packages/workspace-1/package.json | 9 + .../packages/workspace-2/package.json | 9 + .../packages/workspace-3/package.json | 9 + .../a/package.json | 7 + .../b-2/package.json | 4 + .../b/package.json | 7 + .../c/package.json | 7 + .../d/package.json | 4 + .../package.json | 8 + .../packages/workspace-disable-a/package.json | 12 + .../workspace-disable-all/package.json | 12 + .../packages/workspace-hoist-all/package.json | 9 + .../a/package.json | 7 + .../b-2/package.json | 4 + .../b/package.json | 7 + .../c/package.json | 7 + .../d/package.json | 4 + .../package.json | 7 + .../packages/workspace-disable-a/package.json | 12 + .../workspace-disable-all/package.json | 13 + .../packages/workspace-hoist-all/package.json | 9 + .../a/package.json | 7 + .../b-2/package.json | 4 + .../b/package.json | 7 + .../c/package.json | 7 + .../d/package.json | 4 + .../package.json | 8 + .../packages/workspace-disable-a/package.json | 12 + .../workspace-disable-all/package.json | 12 + .../packages/workspace-hoist-all/package.json | 9 + .../why/workspaces-nohoist/package.json | 10 + .../packages/workspace-1/package.json | 12 + .../packages/workspace-2/package.json | 9 + __tests__/package-hoister.js | 530 +++++++++++++++++- src/cli/commands/add.js | 89 ++- src/cli/commands/config.js | 1 + src/cli/commands/install.js | 20 +- src/cli/commands/why.js | 193 ++++--- src/config.js | 79 ++- src/package-hoister.js | 169 +++++- src/reporters/lang/en.js | 9 + src/types.js | 7 +- 52 files changed, 1851 insertions(+), 246 deletions(-) create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-across-versions/a/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-across-versions/b-2/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-across-versions/b/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-across-versions/c/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-across-versions/d/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-across-versions/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-1/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-2/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-3/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-all-from-root/a/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-all-from-root/b-2/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-all-from-root/b/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-all-from-root/c/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-all-from-root/d/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-all-from-root/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-disable-a/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-disable-all/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-hoist-all/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-by-ws/a/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-by-ws/b-2/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-by-ws/b/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-by-ws/c/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-by-ws/d/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-by-ws/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-disable-a/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-disable-all/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-hoist-all/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-some-from-root/a/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-some-from-root/b-2/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-some-from-root/b/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-some-from-root/c/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-some-from-root/d/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-some-from-root/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-disable-a/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-disable-all/package.json create mode 100644 __tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-hoist-all/package.json create mode 100644 __tests__/fixtures/why/workspaces-nohoist/package.json create mode 100644 __tests__/fixtures/why/workspaces-nohoist/packages/workspace-1/package.json create mode 100644 __tests__/fixtures/why/workspaces-nohoist/packages/workspace-2/package.json diff --git a/__tests__/commands/add.js b/__tests__/commands/add.js index 308f7729c3..d9cdde7e3a 100644 --- a/__tests__/commands/add.js +++ b/__tests__/commands/add.js @@ -1,5 +1,4 @@ /* @flow */ - import {ConsoleReporter} from '../../src/reporters/index.js'; import * as reporters from '../../src/reporters/index.js'; import { @@ -107,16 +106,16 @@ test.concurrent('adds any new package to the current workspace, but install from }); }); -test.concurrent('install with arg', (): Promise => { - return runAdd(['is-online'], {}, 'install-with-arg'); +test.concurrent('install with arg', async () => { + await runAdd(['is-online'], {}, 'install-with-arg'); }); -test.concurrent('install from github', (): Promise => { - return runAdd(['substack/node-mkdirp#master'], {}, 'install-github'); +test.concurrent('install from github', async () => { + await runAdd(['substack/node-mkdirp#master'], {}, 'install-github'); }); -test.concurrent('install with --dev flag', (): Promise => { - return runAdd(['left-pad@1.1.0'], {dev: true}, 'add-with-flag', async config => { +test.concurrent('install with --dev flag', async () => { + await runAdd(['left-pad@1.1.0'], {dev: true}, 'add-with-flag', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); @@ -126,8 +125,8 @@ test.concurrent('install with --dev flag', (): Promise => { }); }); -test.concurrent('install with --peer flag', (): Promise => { - return runAdd(['left-pad@1.1.0'], {peer: true}, 'add-with-flag', async config => { +test.concurrent('install with --peer flag', async () => { + await runAdd(['left-pad@1.1.0'], {peer: true}, 'add-with-flag', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); @@ -137,8 +136,8 @@ test.concurrent('install with --peer flag', (): Promise => { }); }); -test.concurrent('install with --optional flag', (): Promise => { - return runAdd(['left-pad@1.1.0'], {optional: true}, 'add-with-flag', async config => { +test.concurrent('install with --optional flag', async () => { + await runAdd(['left-pad@1.1.0'], {optional: true}, 'add-with-flag', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); @@ -183,8 +182,8 @@ const moduleAlreadyInManifestChecker = ({expectWarnings}: {expectWarnings: boole ).toEqual(expectWarnings); }; -test.concurrent('warns when adding a devDependency as dependency', (): Promise => { - return buildRun( +test.concurrent('warns when adding a devDependency as dependency', async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, moduleAlreadyInManifestChecker({expectWarnings: true}), @@ -194,8 +193,8 @@ test.concurrent('warns when adding a devDependency as dependency', (): Promise => { - return buildRun( +test.concurrent("doesn't warn when adding a devDependency as devDependency", async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, moduleAlreadyInManifestChecker({expectWarnings: false}), @@ -205,8 +204,8 @@ test.concurrent("doesn't warn when adding a devDependency as devDependency", (): ); }); -test.concurrent('warns when adding a dependency as devDependency', (): Promise => { - return buildRun( +test.concurrent('warns when adding a dependency as devDependency', async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, moduleAlreadyInManifestChecker({expectWarnings: true}), @@ -216,8 +215,8 @@ test.concurrent('warns when adding a dependency as devDependency', (): Promise => { - return buildRun( +test.concurrent("doesn't warn when adding a dependency as dependency", async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, moduleAlreadyInManifestChecker({expectWarnings: false}), @@ -227,8 +226,8 @@ test.concurrent("doesn't warn when adding a dependency as dependency", (): Promi ); }); -test.concurrent('install with link: specifier', (): Promise => { - return runAdd(['link:../left-pad'], {dev: true}, 'add-with-flag', async config => { +test.concurrent('install with link: specifier', async () => { + await runAdd(['link:../left-pad'], {dev: true}, 'add-with-flag', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); @@ -243,22 +242,22 @@ test.concurrent('install with link: specifier', (): Promise => { }); }); -test.concurrent('install with arg that has binaries', (): Promise => { - return runAdd(['react-native-cli'], {}, 'install-with-arg-and-bin'); +test.concurrent('install with arg that has binaries', async () => { + await runAdd(['react-native-cli'], {}, 'install-with-arg-and-bin'); }); -test.concurrent('add with no manifest creates blank manifest', (): Promise => { - return runAdd(['lodash'], {}, 'add-with-no-manifest', async config => { +test.concurrent('add with no manifest creates blank manifest', async () => { + await runAdd(['lodash'], {}, 'add-with-no-manifest', async config => { expect(await fs.exists(path.join(config.cwd, 'package.json'))).toBe(true); }); }); -test.concurrent('add should ignore cache', (): Promise => { +test.concurrent('add should ignore cache', async () => { // left-pad@1.1.0 gets installed without --save // left-pad@1.1.0 gets installed with --save // files in mirror, yarn.lock, package.json and node_modules should reflect that - return runAdd(['left-pad@1.1.0'], {}, 'install-save-to-mirror-when-cached', async (config, reporter) => { + await runAdd(['left-pad@1.1.0'], {}, 'install-save-to-mirror-when-cached', async (config, reporter) => { expect(await getPackageVersion(config, 'left-pad')).toEqual('1.1.0'); const lockfile = await createLockfile(config.cwd); @@ -286,8 +285,8 @@ test.concurrent('add should ignore cache', (): Promise => { }); }); -test.concurrent('add should not make package.json strict', (): Promise => { - return runAdd(['left-pad@^1.1.0'], {}, 'install-no-strict', async config => { +test.concurrent('add should not make package.json strict', async () => { + await runAdd(['left-pad@^1.1.0'], {}, 'install-no-strict', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); expect(lockfile.indexOf('left-pad@^1.1.0:')).toBeGreaterThanOrEqual(0); @@ -298,8 +297,8 @@ test.concurrent('add should not make package.json strict', (): Promise => }); }); -test.concurrent('add --save-exact should not make all package.json strict', (): Promise => { - return runAdd(['left-pad@1.1.0'], {saveExact: true}, 'install-no-strict-all', async config => { +test.concurrent('add --save-exact should not make all package.json strict', async () => { + await runAdd(['left-pad@1.1.0'], {saveExact: true}, 'install-no-strict-all', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); expect(lockfile.indexOf('left-pad@1.1.0:')).toEqual(0); @@ -310,8 +309,8 @@ test.concurrent('add --save-exact should not make all package.json strict', (): }); }); -test.concurrent('add save-prefix should not expand ~ to home dir', (): Promise => { - return runAdd(['left-pad'], {}, 'install-no-home-expand', async config => { +test.concurrent('add save-prefix should not expand ~ to home dir', async () => { + await runAdd(['left-pad'], {}, 'install-no-home-expand', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); expect(lockfile[0]).toMatch(/^left-pad@~\d+\.\d+\.\d+:$/); expect(JSON.parse(await fs.readFile(path.join(config.cwd, 'package.json'))).dependencies['left-pad']).toMatch( @@ -320,8 +319,8 @@ test.concurrent('add save-prefix should not expand ~ to home dir', (): Promise => { - return runAdd(['left-pad'], {}, 'install-strict-all', async config => { +test.concurrent('add save-exact should make all package.json strict', async () => { + await runAdd(['left-pad'], {}, 'install-strict-all', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); expect(lockfile[0]).toMatch(/^left-pad@\d+\.\d+\.\d+:$/); @@ -331,8 +330,8 @@ test.concurrent('add save-exact should make all package.json strict', (): Promis }); }); -test.concurrent('add with new dependency should be deterministic 3', (): Promise => { - return runAdd([], {}, 'install-should-cleanup-when-package-json-changed-3', async (config, reporter) => { +test.concurrent('add with new dependency should be deterministic 3', async () => { + await runAdd([], {}, 'install-should-cleanup-when-package-json-changed-3', async (config, reporter) => { // expecting yarn check after installation not to fail await fs.copy(path.join(config.cwd, 'yarn.lock.after'), path.join(config.cwd, 'yarn.lock'), reporter); @@ -352,12 +351,12 @@ test.concurrent('add with new dependency should be deterministic 3', (): Promise }); }); -test.concurrent('install --initMirror should add init mirror deps from package.json', (): Promise => { +test.concurrent('install --initMirror should add init mirror deps from package.json', async () => { const mirrorPath = 'mirror-for-offline'; const fixture = 'install-init-mirror'; // initMirror gets converted to save flag in cli/install.js - return runAdd([], {}, fixture, async config => { + await runAdd([], {}, fixture, async config => { expect(await getPackageVersion(config, 'mime-types')).toEqual('2.0.0'); expect(semver.satisfies(await getPackageVersion(config, 'mime-db'), '~1.0.1')).toEqual(true); @@ -374,18 +373,18 @@ test.concurrent('install --initMirror should add init mirror deps from package.j }); }); -test.concurrent('add with new dependency should be deterministic', (): Promise => { +test.concurrent('add with new dependency should be deterministic', async () => { // mime-types@2.0.0->mime-db@1.0.3 is saved in local mirror and is deduped // install mime-db@1.23.0 should move mime-db@1.0.3 deep into mime-types const mirrorPath = 'mirror-for-offline'; const fixture = 'install-deterministic'; - return runInstall({}, path.join('..', 'add', fixture), async (config): Promise => { + await runInstall({}, path.join('..', 'add', fixture), async (config): Promise => { expect(semver.satisfies(await getPackageVersion(config, 'mime-db'), '~1.0.1')).toBe(true); expect(await getPackageVersion(config, 'mime-types')).toEqual('2.0.0'); - return runAdd(['mime-db@1.23.0'], {}, fixture, async config => { + await runAdd(['mime-db@1.23.0'], {}, fixture, async config => { expect(semver.satisfies(await getPackageVersion(config, 'mime-db'), '1.23.0')).toEqual(true); expect(await getPackageVersion(config, 'mime-types')).toEqual('2.0.0'); @@ -412,19 +411,19 @@ test.concurrent('add with new dependency should be deterministic', (): Promise => { +test.concurrent('add with new dependency should be deterministic 2', async () => { // mime-types@2.0.0->mime-db@1.0.1 is saved in local mirror and is deduped // install mime-db@1.0.3 should replace mime-db@1.0.1 in root const mirrorPath = 'mirror-for-offline'; const fixture = 'install-deterministic-2'; - return runInstall({}, path.join('..', 'add', fixture), async (config): Promise => { + await runInstall({}, path.join('..', 'add', fixture), async (config): Promise => { expect(await getPackageVersion(config, 'mime-db')).toEqual('1.0.1'); expect(await getPackageVersion(config, 'mime-types')).toEqual('2.0.0'); - return runAdd(['mime-db@1.0.3'], {}, fixture, async config => { + await runAdd(['mime-db@1.0.3'], {}, fixture, async config => { expect(await getPackageVersion(config, 'mime-db')).toEqual('1.0.3'); expect(await getPackageVersion(config, 'mime-types')).toEqual('2.0.0'); @@ -448,9 +447,9 @@ test.concurrent('add with new dependency should be deterministic 2', (): Promise }); }); -test.concurrent('add with offline mirror', (): Promise => { +test.concurrent('add with offline mirror', async () => { const mirrorPath = 'mirror-for-offline'; - return runAdd(['is-array@^1.0.1'], {}, 'install-with-save-offline-mirror', async config => { + await runAdd(['is-array@^1.0.1'], {}, 'install-with-save-offline-mirror', async config => { const allFiles = await fs.walk(config.cwd); expect( @@ -469,10 +468,10 @@ test.concurrent('add with offline mirror', (): Promise => { }); // broken https://github.com/yarnpkg/yarn/issues/2333 -test.skip('add-then-install git+ssh from offline mirror', (): Promise => { +test.skip('add-then-install git+ssh from offline mirror', async () => { const mirrorPath = 'mirror-for-offline'; - return runAdd( + await runAdd( ['mime-db@git+ssh://git@github.com/jshttp/mime-db.git#1.24.0'], {}, 'install-git-ssh-mirror', @@ -511,9 +510,9 @@ test.skip('add-then-install git+ssh from offline mirror', (): Promise => { ); }); -test.concurrent('install with --save and without offline mirror', (): Promise => { +test.concurrent('install with --save and without offline mirror', async () => { const mirrorPath = 'mirror-for-offline'; - return runAdd(['is-array@^1.0.1'], {}, 'install-with-save-no-offline-mirror', async config => { + await runAdd(['is-array@^1.0.1'], {}, 'install-with-save-no-offline-mirror', async config => { const allFiles = await fs.walk(config.cwd); expect( @@ -531,13 +530,13 @@ test.concurrent('install with --save and without offline mirror', (): Promise => { +test.concurrent('upgrade scenario', async () => { // left-pad first installed 0.0.9 then updated to 1.1.0 // files in mirror, yarn.lock, package.json and node_modules should reflect that const mirrorPath = 'mirror-for-offline'; - return runAdd(['left-pad@0.0.9'], {}, 'install-upgrade-scenario', async (config, reporter): Promise => { + await runAdd(['left-pad@0.0.9'], {}, 'install-upgrade-scenario', async (config, reporter): Promise => { expect(await getPackageVersion(config, 'left-pad')).toEqual('0.0.9'); expect(JSON.parse(await fs.readFile(path.join(config.cwd, 'package.json'))).dependencies).toEqual({ @@ -580,19 +579,19 @@ test.concurrent('upgrade scenario', (): Promise => { }); }); -test.concurrent('upgrade scenario 2 (with sub dependencies)', (): Promise => { +test.concurrent('upgrade scenario 2 (with sub dependencies)', async () => { // mime-types@2.0.0 is saved in local mirror and gets updated to mime-types@2.1.11 // files in mirror, yarn.lock, package.json and node_modules should reflect that const mirrorPath = 'mirror-for-offline'; const fixture = 'install-upgrade-scenario-2'; - return runInstall({}, path.join('..', 'add', fixture), async (config): Promise => { + await runInstall({}, path.join('..', 'add', fixture), async (config): Promise => { expect(semver.satisfies(await getPackageVersion(config, 'mime-db'), '~1.0.1')).toEqual(true); expect(await getPackageVersion(config, 'mime-types')).toEqual('2.0.0'); - return runAdd(['mime-types@2.1.11'], {}, fixture, async config => { + await runAdd(['mime-types@2.1.11'], {}, fixture, async config => { expect(semver.satisfies(await getPackageVersion(config, 'mime-db'), '~1.23.0')).toEqual(true); expect(await getPackageVersion(config, 'mime-types')).toEqual('2.1.11'); @@ -641,11 +640,11 @@ test.concurrent('install another fork of an existing package', (): Promise }); }); -test.concurrent('downgrade scenario', (): Promise => { +test.concurrent('downgrade scenario', async () => { // left-pad first installed 1.1.0 then downgraded to 0.0.9 // files in mirror, yarn.lock, package.json and node_modules should reflect that - return runAdd(['left-pad@1.1.0'], {}, 'install-downgrade-scenario', async (config, reporter): Promise => { + await runAdd(['left-pad@1.1.0'], {}, 'install-downgrade-scenario', async (config, reporter): Promise => { expect(await getPackageVersion(config, 'left-pad')).toEqual('1.1.0'); expect(JSON.parse(await fs.readFile(path.join(config.cwd, 'package.json'))).dependencies).toEqual({ @@ -689,12 +688,12 @@ test.concurrent('downgrade scenario', (): Promise => { }); // https://github.com/yarnpkg/yarn/issues/318 -test.concurrent('modules resolved multiple times should save to mirror correctly', (): Promise => { +test.concurrent('modules resolved multiple times should save to mirror correctly', async () => { // the package.json in this fixture has 4 transitive dependants on module which that should resolve to // which@^1.0.5, which@^1.1.1, which@^1.2.8, which@^1.2.9: // version "1.2.11" // resolved which-1.2.11.tgz#c8b2eeea6b8c1659fa7c1dd4fdaabe9533dc5e8b - return runAdd([], {}, 'no-mirror-remote-when-duplicates', async (config): Promise => { + await runAdd([], {}, 'no-mirror-remote-when-duplicates', async (config): Promise => { const mirrorPath = 'mirror-for-offline'; // check that which module was downloaded to mirror @@ -714,10 +713,10 @@ test.concurrent('modules resolved multiple times should save to mirror correctly }); }); -test.concurrent('add should put a git dependency to mirror', (): Promise => { +test.concurrent('add should put a git dependency to mirror', async () => { const mirrorPath = 'mirror-for-offline'; - return runAdd( + await runAdd( ['mime-db@https://github.com/jshttp/mime-db.git#1.24.0'], {}, 'install-git-mirror', @@ -750,8 +749,8 @@ test.concurrent('add should put a git dependency to mirror', (): Promise = ); }); -test.concurrent('add should store latest version in lockfile', (): Promise => { - return runAdd(['max-safe-integer'], {}, 'latest-version-in-lockfile', async config => { +test.concurrent('add should store latest version in lockfile', async () => { + await runAdd(['max-safe-integer'], {}, 'latest-version-in-lockfile', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); @@ -762,8 +761,8 @@ test.concurrent('add should store latest version in lockfile', (): Promise }); }); -test.concurrent('add should generate correct integrity file', (): Promise => { - return runAdd(['mime-db@1.24.0'], {}, 'integrity-check', async (config, reporter) => { +test.concurrent('add should generate correct integrity file', async () => { + await runAdd(['mime-db@1.24.0'], {}, 'integrity-check', async (config, reporter) => { let allCorrect = true; try { await check(config, reporter, {integrity: true}, []); @@ -784,7 +783,7 @@ test.concurrent('add should generate correct integrity file', (): Promise }); }); -test.concurrent('add infers line endings from existing win32 manifest file', async (): Promise => { +test.concurrent('add infers line endings from existing win32 manifest file', async () => { await runAdd( ['is-online'], {}, @@ -801,7 +800,7 @@ test.concurrent('add infers line endings from existing win32 manifest file', asy ); }); -test.concurrent('add infers line endings from existing unix manifest file', async (): Promise => { +test.concurrent('add infers line endings from existing unix manifest file', async () => { await runAdd( ['is-online'], {}, @@ -819,7 +818,7 @@ test.concurrent('add infers line endings from existing unix manifest file', asyn }); // broken https://github.com/yarnpkg/yarn/issues/2466 -test.skip('add asks for correct package version if user passes an incorrect one', async (): Promise => { +test.skip('add asks for correct package version if user passes an incorrect one', async () => { let chosenVersion = null; await runAdd( ['is-array@100'], @@ -847,8 +846,8 @@ test.skip('add asks for correct package version if user passes an incorrect one' ); }); -test.concurrent('install with latest tag', (): Promise => { - return runAdd(['left-pad@latest'], {}, 'latest-version-in-package', async config => { +test.concurrent('install with latest tag', async () => { + await runAdd(['left-pad@latest'], {}, 'latest-version-in-package', async config => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); const version = await getPackageVersion(config, 'left-pad'); @@ -858,8 +857,8 @@ test.concurrent('install with latest tag', (): Promise => { }); }); -test.concurrent('install with latest tag and --offline flag', (): Promise => { - return runAdd(['left-pad@latest'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => { +test.concurrent('install with latest tag and --offline flag', async () => { + await runAdd(['left-pad@latest'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => { config.offline = true; const add = new Add(['left-pad@latest'], {}, config, reporter, previousAdd.lockfile); await add.init(); @@ -871,8 +870,8 @@ test.concurrent('install with latest tag and --offline flag', (): Promise }); }); -test.concurrent('install with latest tag and --prefer-offline flag', (): Promise => { - return runAdd(['left-pad@1.1.0'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => { +test.concurrent('install with latest tag and --prefer-offline flag', async () => { + await runAdd(['left-pad@1.1.0'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => { config.preferOffline = true; const add = new Add(['left-pad@latest'], {}, config, reporter, previousAdd.lockfile); await add.init(); @@ -885,8 +884,8 @@ test.concurrent('install with latest tag and --prefer-offline flag', (): Promise }); }); -test.concurrent("doesn't warn when peer dependency is met during add", (): Promise => { - return buildRun( +test.concurrent("doesn't warn when peer dependency is met during add", async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, async (args, flags, config, reporter, lockfile): Promise => { @@ -914,8 +913,8 @@ test.concurrent("doesn't warn when peer dependency is met during add", (): Promi ); }); -test.concurrent('warns when peer dependency is not met during add', (): Promise => { - return buildRun( +test.concurrent('warns when peer dependency is not met during add', async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, async (args, flags, config, reporter, lockfile): Promise => { @@ -937,8 +936,8 @@ test.concurrent('warns when peer dependency is not met during add', (): Promise< ); }); -test.concurrent('warns when peer dependency is incorrect during add', (): Promise => { - return buildRun( +test.concurrent('warns when peer dependency is incorrect during add', async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, async (args, flags, config, reporter, lockfile): Promise => { @@ -960,8 +959,8 @@ test.concurrent('warns when peer dependency is incorrect during add', (): Promis ); }); -test.concurrent('should only refer to higher levels to satisfy peer dependency', (): Promise => { - return buildRun( +test.concurrent('should only refer to higher levels to satisfy peer dependency', async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, async (args, flags, config, reporter, lockfile): Promise => { @@ -978,8 +977,8 @@ test.concurrent('should only refer to higher levels to satisfy peer dependency', ); }); -test.concurrent('should refer to deeper dependencies to satisfy peer dependency', (): Promise => { - return buildRun( +test.concurrent('should refer to deeper dependencies to satisfy peer dependency', async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, async (args, flags, config, reporter, lockfile): Promise => { @@ -996,8 +995,8 @@ test.concurrent('should refer to deeper dependencies to satisfy peer dependency' ); }); -test.concurrent('should retain build artifacts after add when missing integrity file', (): Promise => { - return buildRun( +test.concurrent('should retain build artifacts after add when missing integrity file', async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, async (args, flags, config, reporter): Promise => { @@ -1027,8 +1026,8 @@ test.concurrent('should retain build artifacts after add when missing integrity ); }); -test.concurrent('should retain build artifacts after add', (): Promise => { - return buildRun( +test.concurrent('should retain build artifacts after add', async () => { + await buildRun( reporters.BufferReporter, fixturesLoc, async (args, flags, config, reporter, lockfile): Promise => { @@ -1053,10 +1052,10 @@ test.concurrent('should retain build artifacts after add', (): Promise => ); }); -test.concurrent('installing with --pure-lockfile and then adding should keep build artifacts', (): Promise => { +test.concurrent('installing with --pure-lockfile and then adding should keep build artifacts', async () => { const fixture = 'integrity-pure-lockfile'; - return runInstall({pureLockfile: true}, path.join('..', 'add', fixture), async (config, reporter): Promise => { + await runInstall({pureLockfile: true}, path.join('..', 'add', fixture), async (config, reporter): Promise => { expect(await fs.exists(path.join(config.cwd, 'node_modules', '.yarn-integrity'))).toBe(true); expect(await fs.exists(path.join(config.cwd, 'node_modules', 'package-a', 'temp.txt'))).toBe(true); const add = new Add(['left-pad@1.1.0'], {}, config, reporter, await Lockfile.fromDirectory(config.cwd)); @@ -1094,7 +1093,7 @@ test.concurrent('preserves unaffected bin links after adding to workspace packag }); }); -test.concurrent('installs "latest" instead of maxSatisfying if it satisfies requested pattern', (): Promise => { +test.concurrent('installs "latest" instead of maxSatisfying if it satisfies requested pattern', async () => { // Scenario: // If a registry contains versions [1.0.0, 1.0.1, 1.0.2] and latest:1.0.1 // (note that "latest" is not the "newest" version) @@ -1105,7 +1104,7 @@ test.concurrent('installs "latest" instead of maxSatisfying if it satisfies requ // * https://git.io/vFmau // // In this test, `ui-select` has a max version of `0.20.0` but a `latest:0.19.8` - return runAdd(['ui-select@^0.X'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => { + await runAdd(['ui-select@^0.X'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); const patternIndex = lockfile.indexOf('ui-select@^0.X:'); const versionIndex = patternIndex + 1; @@ -1115,14 +1114,14 @@ test.concurrent('installs "latest" instead of maxSatisfying if it satisfies requ }); }); -test.concurrent('installs "latest" instead of maxSatisfying if no requested pattern', (): Promise => { +test.concurrent('installs "latest" instead of maxSatisfying if no requested pattern', async () => { // Scenario: // If a registry contains versions [1.0.0, 1.0.1, 1.0.2] and latest:1.0.1 // If `yarn add` is run, it should choose `1.0.1` because it is "latest", not `1.0.2` even though it is newer. // In other words, when no range is explicitely given, Yarn should choose "latest". // // In this test, `ui-select` has a max version of `0.20.0` but a `latest:0.19.8` - return runAdd(['ui-select'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => { + await runAdd(['ui-select'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => { const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); const patternIndex = lockfile.indexOf('ui-select@^0.19.8:'); const versionIndex = patternIndex + 1; @@ -1131,3 +1130,51 @@ test.concurrent('installs "latest" instead of maxSatisfying if no requested patt expect(actualVersion).toContain('0.19.8'); }); }); + +describe('nohoist', () => { + test.concurrent('can add nohoist pacakge from workspace', async () => { + await runInstall({}, 'workspaces-install-nohoist-across-versions', async (config): Promise => { + const reporter = new ConsoleReporter({}); + + // workspace-2 has b and c since the root has nohoist = ['a', 'b', 'c'] + expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/b`)).toEqual(true); + expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/c`)).toEqual(true); + + // prove package a does not exist in workspace-2 nor in root + expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/a`)).toEqual(false); + expect(await fs.exists(`${config.cwd}/node_modules/a`)).toEqual(false); + expect(await fs.exists(`${config.cwd}/node_modules/b`)).toEqual(false); + expect(await fs.exists(`${config.cwd}/node_modules/c`)).toEqual(false); + + // add package 'a' to workspace-2 + const childConfig = await makeConfigFromDirectory(`${config.cwd}/packages/workspace-2`, reporter, {}); + await add(childConfig, reporter, {}, ['file:a']); + + // now package a should exist in workspace-2 + expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/a`)).toEqual(true); + expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/b`)).toEqual(true); + expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/c`)).toEqual(true); + + // make sure workspace-2 dependencies didn't get hoisted to root + expect(await fs.exists(`${config.cwd}/node_modules/a`)).toEqual(false); + expect(await fs.exists(`${config.cwd}/node_modules/b`)).toEqual(false); + expect(await fs.exists(`${config.cwd}/node_modules/c`)).toEqual(false); + }); + }); + test.concurrent('can add nohoist pacakge from root', async () => { + await runInstall({}, 'workspaces-install-nohoist-across-versions', async (config): Promise => { + const reporter = new ConsoleReporter({}); + + // prove package a does not exist in workspace-2 nor in root + expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/a`)).toEqual(false); + expect(await fs.exists(`${config.cwd}/node_modules/a`)).toEqual(false); + + // add package 'a' to root package + await add(config, reporter, {ignoreWorkspaceRootCheck: true}, ['file:a']); + + // now package a should exist in workspace-2 + expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/a`)).toEqual(false); + expect(await fs.exists(`${config.cwd}/node_modules/a`)).toEqual(true); + }); + }); +}); diff --git a/__tests__/commands/install/workspaces-install.js b/__tests__/commands/install/workspaces-install.js index 55ed6ce173..0afe5971ff 100644 --- a/__tests__/commands/install/workspaces-install.js +++ b/__tests__/commands/install/workspaces-install.js @@ -4,7 +4,8 @@ import {run as check} from '../../../src/cli/commands/check.js'; import {Install, run as install} from '../../../src/cli/commands/install.js'; import * as reporters from '../../../src/reporters/index.js'; import * as fs from '../../../src/util/fs.js'; -import {runInstall, run as buildRun, makeConfigFromDirectory} from '../_helpers.js'; +import type ConfigType from '../../../src/config.js'; +import {runInstall, run as buildRun, makeConfigFromDirectory, isPackagePresent} from '../_helpers.js'; jasmine.DEFAULT_TIMEOUT_INTERVAL = 150000; @@ -272,3 +273,119 @@ test.concurrent('install should link binaries properly when run from child works }); // TODO need more thorough tests for all kinds of checks: integrity, verify-tree + +describe('nohoist', () => { + async function checkPackage(config: ConfigType, path: string, shouldPresent: boolean): Promise { + const isPresent = await isPackagePresent(config, path); + try { + expect(isPresent).toEqual(shouldPresent); + } catch (e) { + throw new Error(`error: ${path} should ${shouldPresent ? '' : 'NOT'} exist`); + } + } + + test.concurrent('exclude packages by workspace', (): Promise => { + return runInstall({}, 'workspaces-install-nohoist-by-ws', async (config): Promise => { + const existingPackages = [ + 'workspace-disable-a', + 'workspace-disable-all', + 'workspace-hoist-all', + 'workspace-disable-all/c', + 'workspace-disable-all/b', + 'workspace-disable-all/d', + 'workspace-disable-a/a', + 'workspace-disable-a/b', + 'workspace-disable-all/workspace-hoist-all', + 'b', + 'c', + 'd', + ]; + const notExistingPackages = ['a', 'workspace-hoist-all/b', 'workspace-hoist-all/d']; + + for (const p of existingPackages) { + await checkPackage(config, p, true); + } + for (const p of notExistingPackages) { + await checkPackage(config, p, false); + } + }); + }); + + test.concurrent('disable all hoist for every workspace', (): Promise => { + return runInstall({}, 'workspaces-install-nohoist-all-from-root', async config => { + const existingPackages = [ + 'workspace-disable-a', + 'workspace-disable-all', + 'workspace-hoist-all', + 'workspace-disable-all/c', + 'workspace-disable-all/b', + 'workspace-disable-all/d', + 'workspace-disable-a/a', + 'workspace-disable-a/b', + 'workspace-disable-a/d', + 'workspace-hoist-all/b', + 'workspace-hoist-all/d', + ]; + const notExistingPackages = ['a', 'b', 'c', 'd']; + + for (const p of existingPackages) { + await checkPackage(config, p, true); + } + for (const p of notExistingPackages) { + await checkPackage(config, p, false); + } + }); + }); + test.concurrent('disable some hoist for every workspace', (): Promise => { + return runInstall({}, 'workspaces-install-nohoist-some-from-root', async config => { + const existingPackages = [ + 'workspace-disable-a', + 'workspace-disable-all', + 'workspace-hoist-all', + 'workspace-disable-all/c', + 'workspace-disable-all/b', + 'workspace-disable-all/d', + 'workspace-disable-a/a', + 'workspace-disable-a/b', + 'workspace-disable-a/d', + 'workspace-hoist-all/d', + 'c', + 'b', + ]; + const notExistingPackages = ['a', 'd']; + + for (const p of existingPackages) { + await checkPackage(config, p, true); + } + for (const p of notExistingPackages) { + await checkPackage(config, p, false); + } + }); + }); + test.concurrent('disable hoisting package across versions', (): Promise => { + return runInstall({}, 'workspaces-install-nohoist-across-versions', async config => { + const existingPackages = [ + 'workspace-1', + 'workspace-2', + 'workspace-3', + 'workspace-1/c', + 'workspace-1/b', + 'workspace-1/a', + 'workspace-2/b', + 'workspace-2/c', + 'workspace-2/b', + 'workspace-2/c/b', + 'workspace-3/b', + 'd', + ]; + const notExistingPackages = ['a', 'b', 'c', 'workspace-3/d']; + + for (const p of existingPackages) { + await checkPackage(config, p, true); + } + for (const p of notExistingPackages) { + await checkPackage(config, p, false); + } + }); + }); +}); diff --git a/__tests__/commands/why.js b/__tests__/commands/why.js index 0580a5b889..88a86c44a8 100644 --- a/__tests__/commands/why.js +++ b/__tests__/commands/why.js @@ -1,10 +1,14 @@ /* @flow */ import {BufferReporter} from '../../src/reporters/index.js'; -import {run as why} from '../../src/cli/commands/why.js'; +import {run as why, queryWhy} from '../../src/cli/commands/why.js'; import * as reporters from '../../src/reporters/index.js'; import Config from '../../src/config.js'; import path from 'path'; +import {HoistManifest} from '../../src/package-hoister.js'; +import type {Manifest} from '../../src/types.js'; +import type {HoistManifestTuple, HoistManifestTuples} from '../../src/package-hoister.js'; +import type {LanguageKeys} from '../../src/reporters/lang/en.js'; jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000; @@ -15,9 +19,10 @@ async function runWhy( args: Array, name: string, checkSteps?: ?(config: Config, reporter: BufferReporter) => ?Promise, + _reporter?: reporters.BufferReporter, ): Promise { const cwd = path.join(fixturesLoc, name); - const reporter = new reporters.BufferReporter({stdout: null, stdin: null}); + const reporter = _reporter || new reporters.BufferReporter({stdout: null, stdin: null}); try { const config = await Config.create({cwd}, reporter); @@ -94,7 +99,7 @@ test.concurrent('should determine that the module installed because it is in dev test.concurrent('should determine that the module installed because mime-types depend on it', (): Promise => { return runWhy({}, ['mime-db'], 'basic', (config, reporter) => { const report = reporter.getBuffer(); - expect(report[report.length - 1].data).toEqual(reporter.lang('whyDependedOnSimple', 'mime-types')); + expect((report[report.length - 1].data: any).items).toContainEqual(reporter.lang('whyDependedOn', 'mime-types')); }); }); @@ -115,9 +120,150 @@ test('should report when a module is included multiple times including the root' .map(entry => entry.data.items)[0]; expect(reasons).toEqual([ - '"b#caniuse-api" depends on it', - '"b#caniuse-api#browserslist" depends on it', 'Specified in "dependencies"', + 'Hoisted from "b#caniuse-api#caniuse-lite"', + 'Hoisted from "b#caniuse-api#browserslist#caniuse-lite"', ]); }); }); + +class MockReporter extends reporters.BufferReporter { + _lang = jest.fn(); + lang(key: LanguageKeys, ...args: Array): string { + this._lang(key, args); + return super.lang(key, args); + } + + findCalls(key: string): Array> { + return this._lang.mock.calls.filter(call => { + return call[0] === key; + }); + } +} + +describe('reports multiple occurrences', () => { + function setupTest( + target: string, + checkSteps: (config: Config, reporter: MockReporter) => ?Promise, + ): Promise { + const _reporter = new MockReporter({stdout: null, stdin: null}); + return runWhy( + {includeWorkspaceDeps: true}, + [target], + 'workspaces-nohoist', + (config, reporter) => checkSteps(config, _reporter), + _reporter, + ); + } + test.concurrent('due to nohoist', (): Promise => { + const target = 'mime-types'; + return setupTest(target, (config, reporter) => { + // check packages matched + let calls = reporter.findCalls('whyMatch'); + expect(calls.length).toEqual(2); + + const found: [boolean, boolean] = [false, false]; + calls.forEach(call => { + const pkg: string = call[1][0]; + if (pkg.indexOf(target) === 0) { + found[0] = true; + } else if (pkg.indexOf(`#${target}`) > 0) { + found[1] = true; + } + }); + expect(found[0]).toEqual(true); + expect(found[1]).toEqual(true); + + // check reasons: should have both hoist and nohoist + calls = reporter.findCalls('whyHoistedTo'); + expect(calls.length).toEqual(1); + expect(calls[0][1][0]).toEqual(target); + + calls = reporter.findCalls('whyNotHoisted'); + expect(calls.length).toEqual(1); + const nohoistList = calls[0][1][0]; + let found2 = false; + for (const p of nohoistList) { + if (p.indexOf(target) >= 0) { + found2 = true; + break; + } + } + expect(found2).toBeTruthy(); + }); + }); + test.concurrent('due to version conflict', (): Promise => { + const target = 'uglifyify'; + return setupTest(target, (config, reporter) => { + // check packages matched + let calls = reporter.findCalls('whyMatch'); + expect(calls.length).toEqual(2); + + const found: [boolean, boolean] = [false, false]; + calls.forEach(call => { + const pkg: string = call[1][0]; + if (pkg.indexOf(target) === 0) { + found[0] = true; + } else if (pkg.indexOf(`#${target}`) > 0) { + found[1] = true; + } + }); + expect(found[0]).toEqual(true); + expect(found[1]).toEqual(true); + + // check reasons: should have both hoist and nohoist + calls = reporter.findCalls('whySpecified'); + expect(calls.length).toEqual(2); + }); + }); +}); + +describe('queryWhy', () => { + function mockManifest(name: string): Manifest { + return { + name, + version: '1.0.0', + _uid: '', + }; + } + + function mockHoistManifestTuple(name: string, key: string, previousPaths: Array): HoistManifestTuple { + const hm = new HoistManifest(key, [], mockManifest(name), '', false, true, false); + return ['', hm]; + } + + function validateMatch(matches: Array, expected: Array) { + expect(matches.length).toEqual(expected.length); + for (let i = 0; i < matches.length; i++) { + expect(matches[i][1].key).toEqual(expected[i]); + } + } + + test('can determine a nohoist module', () => { + const hoisted: HoistManifestTuples = [ + mockHoistManifestTuple('b', 'b', ['workspace-1#b']), + mockHoistManifestTuple('a', 'workspace-1#a', []), + ]; + validateMatch(queryWhy('a', hoisted), ['workspace-1#a']); + validateMatch(queryWhy('b', hoisted), ['b']); + }); + test('can determine a deep nohoist module', () => { + const hoisted: HoistManifestTuples = [ + mockHoistManifestTuple('b', 'b', ['workspace-1#b']), + mockHoistManifestTuple('c', 'workspace-1#a#c', []), + mockHoistManifestTuple('a', 'workspace-1#a', []), + ]; + validateMatch(queryWhy('a', hoisted), ['workspace-1#a']); + validateMatch(queryWhy('c', hoisted), ['workspace-1#a#c']); + validateMatch(queryWhy('a#c', hoisted), ['workspace-1#a#c']); + }); + test('can return multiple matches', () => { + const hoisted: HoistManifestTuples = [ + mockHoistManifestTuple('b', 'b', ['workspace-1#b']), + mockHoistManifestTuple('b', 'c#b', []), + mockHoistManifestTuple('a', 'workspace-1#a', []), + mockHoistManifestTuple('c', 'c', ['workspace-1#c']), + ]; + validateMatch(queryWhy('b', hoisted), ['b', 'c#b']); + }); +}); diff --git a/__tests__/config.js b/__tests__/config.js index b188305c10..8c52a3ba1a 100644 --- a/__tests__/config.js +++ b/__tests__/config.js @@ -1,7 +1,8 @@ /* @flow */ -import Config from '../src/config.js'; -import {ConsoleReporter} from '../src/reporters/index.js'; +import Config, {extractWorkspaces} from '../src/config.js'; +import {ConsoleReporter, BufferReporter} from '../src/reporters/index.js'; +import type {WorkspacesConfig, Manifest} from '../src/types.js'; const stream = require('stream'); @@ -42,3 +43,181 @@ test('getOption does not change empty-string when resolve=false', async () => { config.registries.yarn.config.cafile = ''; expect(config.getOption('cafile', false)).toEqual(''); }); + +describe('workspaces config', () => { + function createWorkspaceManifest(packages: Array, nohoist: Array): Manifest { + const workspaces: WorkspacesConfig = { + packages, + nohoist, + }; + const manifest: Manifest = { + _uid: 'whatever', + version: '1.0', + name: 'whatever', + private: true, + workspaces, + }; + + return manifest; + } + function validateWS(expected: ?WorkspacesConfig, actual: ?WorkspacesConfig) { + if (!expected) { + expect(actual).toBeUndefined(); + return; + } + if (!actual) { + expect(actual).not.toBeUndefined(); + return; + } + + expect(actual.packages).toEqual(expected.packages); + expect(actual.nohoist).toEqual(expected.nohoist); + } + test('accessing workspaces config requires explicit enabling', async () => { + const config = await initConfig({}); + const packages = ['w1', 'w2']; + const nohoist = ['a']; + const manifest = createWorkspaceManifest(packages, nohoist); + + config.workspacesEnabled = false; + expect(config.getWorkspaces(manifest)).toBeUndefined(); + + config.workspacesEnabled = true; + const ws = config.getWorkspaces(manifest); + if (!ws) { + expect(ws).not.toBeUndefined(); + } else { + expect(ws.packages).toEqual(packages); + expect(ws.nohoist).toEqual(nohoist); + } + }); + + test('can adapt legacy workspaces to new format', () => { + const packages = ['w1', 'w2']; + const nohoist = ['a']; + const manifest = createWorkspaceManifest(packages, nohoist); + + const expected: WorkspacesConfig = { + packages, + nohoist, + }; + + // manifest.workspaces = newWorkspaces; + validateWS(expected, extractWorkspaces(manifest)); + + manifest.workspaces = packages; + expected.nohoist = undefined; + validateWS(expected, extractWorkspaces(manifest)); + + manifest.workspaces = undefined; + validateWS(undefined, extractWorkspaces(manifest)); + + manifest.workspaces = {}; + validateWS(undefined, extractWorkspaces(manifest)); + }); + test('workspaces is eligibile only for private packages', async () => { + const config = await initConfig({}); + const packages = ['w1', 'w2']; + const nohoist = ['a']; + const manifest = createWorkspaceManifest(packages, nohoist); + config.workspacesEnabled = true; + expect(config.getWorkspaces(manifest)).not.toBeUndefined(); + + manifest.private = false; + expect(config.getWorkspaces(manifest)).toBeUndefined(); + }); + test('nohoist is eligibile only for private packages and workspacesNohoistEnabled', async () => { + const config = await initConfig({}); + const packages = ['w1', 'w2']; + const nohoist = ['a']; + const manifest = createWorkspaceManifest(packages, nohoist); + + // any one of these flag would turn off nohoist + function testNohoistEligibility(isPrivate: boolean, workspacesNohoistEnabled: boolean, expectEligibility: boolean) { + manifest.private = isPrivate; + config.workspacesNohoistEnabled = workspacesNohoistEnabled; + const ws = config.getWorkspaces(manifest); + if (ws) { + if (!expectEligibility) { + expect(ws.nohoist).toBeUndefined(); + } else { + expect(ws.nohoist).toEqual(nohoist); + } + } else { + if (expectEligibility) { + expect(ws).not.toBeUndefined(); + } + } + } + + testNohoistEligibility(true, false, false); + testNohoistEligibility(false, true, false); + testNohoistEligibility(true, true, true); + }); + test('can throw exception for eligibility violation', async () => { + const config = await initConfig({}); + const packages = ['w1', 'w2']; + const nohoist = ['a']; + const manifest = createWorkspaceManifest(packages, nohoist); + + manifest.private = false; + const ws = config.getWorkspaces(manifest); + expect(ws).toBeUndefined(); + + try { + config.getWorkspaces(manifest, true); + expect(`exception to be thrown`).toEqual('but it did not...'); + } catch (e) { + // ok + } + + // should not thrown if manifest is eligibile + manifest.private = true; + expect(config.getWorkspaces(manifest, true)).not.toBeUndefined(); + }); + test('can report eligibility warnings', async () => { + const config = await initConfig({}); + const nohoist = ['a']; + const manifest = createWorkspaceManifest([], nohoist); + + function getNohoist(ws: ?WorkspacesConfig): ?Array { + return ws ? ws.nohoist : undefined; + } + + const mockReporter = new MockReporter(); + config.reporter = mockReporter; + + // when everything is fine, reporter should be empty + expect(getNohoist(config.getWorkspaces(manifest, false))).not.toBeUndefined(); + expect(mockReporter.numberOfCalls()).toEqual(0); + + config.workspacesNohoistEnabled = false; + expect(getNohoist(config.getWorkspaces(manifest, false))).toBeUndefined(); + expect(mockReporter.numberOfCalls()).toEqual(1); + expect(mockReporter.findCalls('workspacesNohoistDisabled').length).toEqual(1); + + mockReporter.reset(); + + config.workspacesNohoistEnabled = true; + manifest.private = false; + expect(getNohoist(config.getWorkspaces(manifest, false))).toBeUndefined(); + expect(mockReporter.numberOfCalls()).toEqual(1); + expect(mockReporter.findCalls('workspacesNohoistRequirePrivatePackages').length).toEqual(1); + }); +}); + +class MockReporter extends BufferReporter { + lang = jest.fn(); + + findCalls(key: string): Array> { + return this.lang.mock.calls.filter(call => { + return call[0] === key; + }); + } + numberOfCalls(): number { + return this.lang.mock.calls.length; + } + reset() { + this.lang.mockReset(); + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/a/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/a/package.json new file mode 100644 index 0000000000..0f628dcd04 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "0.0.0", + "dependencies": { + "b": "file:../b" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/b-2/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/b-2/package.json new file mode 100644 index 0000000000..57549744f3 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/b-2/package.json @@ -0,0 +1,4 @@ +{ + "name": "b", + "version": "2.0.0" +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/b/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/b/package.json new file mode 100644 index 0000000000..64fa5bdefa --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/b/package.json @@ -0,0 +1,7 @@ +{ + "name": "b", + "version": "0.0.0", + "dependencies": { + "c": "file:../c" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/c/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/c/package.json new file mode 100644 index 0000000000..0c0656c6d6 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/c/package.json @@ -0,0 +1,7 @@ +{ + "name": "c", + "version": "0.0.0", + "dependencies": { + "b": "file:../b-2" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/d/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/d/package.json new file mode 100644 index 0000000000..38bc130e4d --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/d/package.json @@ -0,0 +1,4 @@ +{ + "name": "d", + "version": "0.0.0" +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/package.json new file mode 100644 index 0000000000..e214916309 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/package.json @@ -0,0 +1,8 @@ +{ + "name": "my-project", + "private": true, + "workspaces": { + "packages": ["packages/*"], + "nohoist": ["**/a", "**/b", "**/c"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-1/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-1/package.json new file mode 100644 index 0000000000..0cc3ae718d --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-1/package.json @@ -0,0 +1,9 @@ +{ + "name": "workspace-1", + "version": "1.0.0", + "private": true, + "dependencies": { + "a": "file:../../a", + "c": "file:../../c" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-2/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-2/package.json new file mode 100644 index 0000000000..bb344c7f76 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-2/package.json @@ -0,0 +1,9 @@ +{ + "name": "workspace-2", + "version": "1.0.0", + "private": true, + "dependencies": { + "b": "file:../../b", + "c": "file:../../c" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-3/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-3/package.json new file mode 100644 index 0000000000..1f89e05677 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-across-versions/packages/workspace-3/package.json @@ -0,0 +1,9 @@ +{ + "name": "workspace-3", + "version": "1.0.0", + "private": true, + "dependencies": { + "b": "file:../../b-2", + "d": "file:../../d" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/a/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/a/package.json new file mode 100644 index 0000000000..0f628dcd04 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "0.0.0", + "dependencies": { + "b": "file:../b" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/b-2/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/b-2/package.json new file mode 100644 index 0000000000..57549744f3 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/b-2/package.json @@ -0,0 +1,4 @@ +{ + "name": "b", + "version": "2.0.0" +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/b/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/b/package.json new file mode 100644 index 0000000000..64fa5bdefa --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/b/package.json @@ -0,0 +1,7 @@ +{ + "name": "b", + "version": "0.0.0", + "dependencies": { + "c": "file:../c" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/c/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/c/package.json new file mode 100644 index 0000000000..0c0656c6d6 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/c/package.json @@ -0,0 +1,7 @@ +{ + "name": "c", + "version": "0.0.0", + "dependencies": { + "b": "file:../b-2" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/d/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/d/package.json new file mode 100644 index 0000000000..38bc130e4d --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/d/package.json @@ -0,0 +1,4 @@ +{ + "name": "d", + "version": "0.0.0" +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/package.json new file mode 100644 index 0000000000..27c227f3e0 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/package.json @@ -0,0 +1,8 @@ +{ + "name": "my-project", + "private": true, + "workspaces": { + "packages": ["packages/*"], + "nohoist": ["**"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-disable-a/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-disable-a/package.json new file mode 100644 index 0000000000..0016f8be81 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-disable-a/package.json @@ -0,0 +1,12 @@ +{ + "name": "workspace-disable-a", + "version": "1.0.0", + "private": true, + "dependencies": { + "a": "file:../../a", + "d": "file:../../d" + }, + "workspaces": { + "nohoist": ["a"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-disable-all/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-disable-all/package.json new file mode 100644 index 0000000000..49120d2521 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-disable-all/package.json @@ -0,0 +1,12 @@ +{ + "name": "workspace-disable-all", + "version": "1.0.0", + "private": true, + "dependencies": { + "c": "file:../../c", + "d": "file:../../d" + }, + "workspaces": { + "nohoist": ["**"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-hoist-all/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-hoist-all/package.json new file mode 100644 index 0000000000..47168c950c --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-all-from-root/packages/workspace-hoist-all/package.json @@ -0,0 +1,9 @@ +{ + "name": "workspace-hoist-all", + "version": "1.0.0", + "private": true, + "dependencies": { + "b": "file:../../b-2", + "d": "file:../../d" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/a/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/a/package.json new file mode 100644 index 0000000000..0f628dcd04 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "0.0.0", + "dependencies": { + "b": "file:../b" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/b-2/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/b-2/package.json new file mode 100644 index 0000000000..57549744f3 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/b-2/package.json @@ -0,0 +1,4 @@ +{ + "name": "b", + "version": "2.0.0" +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/b/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/b/package.json new file mode 100644 index 0000000000..64fa5bdefa --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/b/package.json @@ -0,0 +1,7 @@ +{ + "name": "b", + "version": "0.0.0", + "dependencies": { + "c": "file:../c" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/c/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/c/package.json new file mode 100644 index 0000000000..0c0656c6d6 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/c/package.json @@ -0,0 +1,7 @@ +{ + "name": "c", + "version": "0.0.0", + "dependencies": { + "b": "file:../b-2" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/d/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/d/package.json new file mode 100644 index 0000000000..38bc130e4d --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/d/package.json @@ -0,0 +1,4 @@ +{ + "name": "d", + "version": "0.0.0" +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/package.json new file mode 100644 index 0000000000..8d9019a1f3 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/package.json @@ -0,0 +1,7 @@ +{ + "name": "my-project", + "private": true, + "workspaces": { + "packages": ["packages/*"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-disable-a/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-disable-a/package.json new file mode 100644 index 0000000000..0016f8be81 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-disable-a/package.json @@ -0,0 +1,12 @@ +{ + "name": "workspace-disable-a", + "version": "1.0.0", + "private": true, + "dependencies": { + "a": "file:../../a", + "d": "file:../../d" + }, + "workspaces": { + "nohoist": ["a"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-disable-all/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-disable-all/package.json new file mode 100644 index 0000000000..056f9e0117 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-disable-all/package.json @@ -0,0 +1,13 @@ +{ + "name": "workspace-disable-all", + "version": "1.0.0", + "private": true, + "dependencies": { + "c": "file:../../c", + "d": "file:../../d", + "workspace-hoist-all": "^1.0.0" + }, + "workspaces": { + "nohoist": ["**"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-hoist-all/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-hoist-all/package.json new file mode 100644 index 0000000000..47168c950c --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-by-ws/packages/workspace-hoist-all/package.json @@ -0,0 +1,9 @@ +{ + "name": "workspace-hoist-all", + "version": "1.0.0", + "private": true, + "dependencies": { + "b": "file:../../b-2", + "d": "file:../../d" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/a/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/a/package.json new file mode 100644 index 0000000000..0f628dcd04 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "0.0.0", + "dependencies": { + "b": "file:../b" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/b-2/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/b-2/package.json new file mode 100644 index 0000000000..57549744f3 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/b-2/package.json @@ -0,0 +1,4 @@ +{ + "name": "b", + "version": "2.0.0" +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/b/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/b/package.json new file mode 100644 index 0000000000..64fa5bdefa --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/b/package.json @@ -0,0 +1,7 @@ +{ + "name": "b", + "version": "0.0.0", + "dependencies": { + "c": "file:../c" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/c/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/c/package.json new file mode 100644 index 0000000000..0c0656c6d6 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/c/package.json @@ -0,0 +1,7 @@ +{ + "name": "c", + "version": "0.0.0", + "dependencies": { + "b": "file:../b-2" + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/d/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/d/package.json new file mode 100644 index 0000000000..38bc130e4d --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/d/package.json @@ -0,0 +1,4 @@ +{ + "name": "d", + "version": "0.0.0" +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/package.json new file mode 100644 index 0000000000..10abfeab74 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/package.json @@ -0,0 +1,8 @@ +{ + "name": "my-project", + "private": true, + "workspaces": { + "packages": ["packages/*"], + "nohoist": ["**/d"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-disable-a/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-disable-a/package.json new file mode 100644 index 0000000000..0016f8be81 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-disable-a/package.json @@ -0,0 +1,12 @@ +{ + "name": "workspace-disable-a", + "version": "1.0.0", + "private": true, + "dependencies": { + "a": "file:../../a", + "d": "file:../../d" + }, + "workspaces": { + "nohoist": ["a"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-disable-all/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-disable-all/package.json new file mode 100644 index 0000000000..49120d2521 --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-disable-all/package.json @@ -0,0 +1,12 @@ +{ + "name": "workspace-disable-all", + "version": "1.0.0", + "private": true, + "dependencies": { + "c": "file:../../c", + "d": "file:../../d" + }, + "workspaces": { + "nohoist": ["**"] + } +} diff --git a/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-hoist-all/package.json b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-hoist-all/package.json new file mode 100644 index 0000000000..47168c950c --- /dev/null +++ b/__tests__/fixtures/install/workspaces-install-nohoist-some-from-root/packages/workspace-hoist-all/package.json @@ -0,0 +1,9 @@ +{ + "name": "workspace-hoist-all", + "version": "1.0.0", + "private": true, + "dependencies": { + "b": "file:../../b-2", + "d": "file:../../d" + } +} diff --git a/__tests__/fixtures/why/workspaces-nohoist/package.json b/__tests__/fixtures/why/workspaces-nohoist/package.json new file mode 100644 index 0000000000..5ea0ec1e73 --- /dev/null +++ b/__tests__/fixtures/why/workspaces-nohoist/package.json @@ -0,0 +1,10 @@ +{ + "private": true, + "workspaces": { + "packages": ["packages/*"], + "nohoist": ["mime-db"] + }, + "devDependencies": { + "left-pad": "1.1.3" + } +} diff --git a/__tests__/fixtures/why/workspaces-nohoist/packages/workspace-1/package.json b/__tests__/fixtures/why/workspaces-nohoist/packages/workspace-1/package.json new file mode 100644 index 0000000000..2f31a8c858 --- /dev/null +++ b/__tests__/fixtures/why/workspaces-nohoist/packages/workspace-1/package.json @@ -0,0 +1,12 @@ +{ + "name": "workspace-1", + "version": "1.0.0", + "private": true, + "workspaces": { + "nohoist": ["mime-types"] + }, + "dependencies": { + "mime-types": "2.1.12", + "uglifyify": "3.0.0" + } +} diff --git a/__tests__/fixtures/why/workspaces-nohoist/packages/workspace-2/package.json b/__tests__/fixtures/why/workspaces-nohoist/packages/workspace-2/package.json new file mode 100644 index 0000000000..ba904dd210 --- /dev/null +++ b/__tests__/fixtures/why/workspaces-nohoist/packages/workspace-2/package.json @@ -0,0 +1,9 @@ +{ + "name": "workspace-2", + "version": "1.0.0", + "private": false, + "dependencies": { + "mime-types": "2.1.12", + "uglifyify": "3.0.4" + } +} diff --git a/__tests__/package-hoister.js b/__tests__/package-hoister.js index 4f29557503..c26b0180d9 100644 --- a/__tests__/package-hoister.js +++ b/__tests__/package-hoister.js @@ -4,8 +4,12 @@ import PackageHoister, {HoistManifest} from '../src/package-hoister.js'; import PackageResolver from '../src/package-resolver.js'; import Lockfile from '../src/lockfile'; import type PackageReference from '../src/package-reference.js'; +import {extractWorkspaces} from '../src/config.js'; import type Config from '../src/config.js'; -import type {Manifest} from '../src/types.js'; +import type {Manifest, WorkspacesManifestMap, WorkspacesConfig} from '../src/types.js'; +import WorkspaceLayout from '../src/workspace-layout.js'; +import {getPackagePath} from './commands/_helpers.js'; +import mm from 'micromatch'; const path = require('path'); @@ -28,16 +32,29 @@ function createManifestForUid(uid, dependencies): Manifest { // key is the module uid, in the form name@version ('lodash@1.2.3') // value is an array of strings of dependencies (['lodash@1.2.3', 'grunt@4.5.6']) // These modules will be loaded into a mock PackageResolver that will use the hash's keys to resolve the package. -function createTestFixture(testModules: any = {}): any { - const config = (({ +type UpdateResolver = (resolver: PackageResolver, config: Config) => void; + +function createTestFixture( + testModules: any = {}, + workspacesEnabled: boolean = true, + updateResolver?: UpdateResolver, +): any { + const config: Config = (({ cwd: CWD, lockfileFolder: CWD, + workspacesEnabled, getFolder(): string { return 'node_modules'; }, generateHardModulePath(pkg: ?PackageReference): string { return pkg ? pkg.uid : ''; }, + getWorkspaces(manifest: ?Manifest): ?WorkspacesConfig { + if (this.workspacesEnabled) { + return extractWorkspaces(manifest); + } + return undefined; + }, }: any): Config); // build Manifests with just enough information to get the PackageHoister to work. @@ -50,6 +67,10 @@ function createTestFixture(testModules: any = {}): any { packageResolver.addPattern(uid, packageManifest); }); + if (updateResolver) { + updateResolver(packageResolver, config); + } + const packageHoister = new PackageHoister(config, packageResolver); const atPath = function(...installPaths): string { @@ -72,6 +93,7 @@ function createTestFixture(testModules: any = {}): any { const toContainPackage = function(received: any, ...expected: any): JestMatcherResult { const [uid, expectedInstallPath] = expected; + let pass: boolean = false; received.forEach(pkg => { const [location: string, hoistManifest: HoistManifest] = pkg; @@ -311,3 +333,505 @@ test('will hoist packages under subdirectories when they cannot hoist to root', expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); expect(result).toContainPackage('d@1.0.0', atPath('a', 'node_modules', 'd')); }); + +describe('nohoist', () => { + test('nohoist can be turned off by disable workspaces (workspaces-experimental)', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture( + { + 'a@1.0.0': ['c@1.0.0'], + 'b@2.0.0': [], + 'c@1.0.0': [], + }, + false, + ); + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['c']}; + + packageHoister.seed(['a@1.0.0', 'b@2.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(3); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@2.0.0', atPath('b')); + expect(result).toContainPackage('c@1.0.0', atPath('c')); + }); + describe('nohoist = hoist to the top of its branch instead of root', () => { + function fixture(): any { + return createTestFixture({ + 'a@1.0.0': ['c@1.0.0'], + 'b@1.0.0': ['c@1.0.0'], + 'c@1.0.0': ['d@1.0.0'], + 'd@1.0.0': [], + }); + } + test('shallow nohoist', () => { + const {atPath, packageHoister, packageResolver} = fixture(); + + // nohoist a/c + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['c']}; + + packageHoister.seed(['a@1.0.0', 'b@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(5); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@1.0.0', atPath('b')); + expect(result).toContainPackage('c@1.0.0', atPath('c')); + expect(result).toContainPackage('d@1.0.0', atPath('d')); + expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); + }); + test('deep nohoist', () => { + const {atPath, packageHoister, packageResolver} = fixture(); + + // nohoist a/c and everything under a/c + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['c', 'c/**']}; + + packageHoister.seed(['a@1.0.0', 'b@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(6); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@1.0.0', atPath('b')); + expect(result).toContainPackage('c@1.0.0', atPath('c')); + expect(result).toContainPackage('d@1.0.0', atPath('d')); + expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); + expect(result).toContainPackage('d@1.0.0', atPath('a', 'node_modules', 'd')); + }); + }); + test('nohoist pkg will be duplicated independent of the hoisted version', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture({ + 'a@1.0.0': ['c@1.0.0'], + 'b@1.0.0': ['c@1.0.0'], + 'c@1.0.0': ['d@1.0.0'], + 'd@1.0.0': [], + }); + + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['c']}; + + packageHoister.seed(['a@1.0.0', 'b@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(5); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@1.0.0', atPath('b')); + expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); + expect(result).toContainPackage('c@1.0.0', atPath('c')); + expect(result).toContainPackage('d@1.0.0', atPath('d')); + }); + test('nohoist pkg will NOT be duplicated within the same branch', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture({ + 'a@1.0.0': ['b@1.0.0', 'c@1.0.0'], + 'b@1.0.0': ['d@1.0.0'], + 'c@1.0.0': ['d@1.0.0'], + 'd@1.0.0': [], + }); + + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['b', 'c', '**/d']}; + + packageHoister.seed(['a@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(4); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@1.0.0', atPath('a', 'node_modules', 'b')); + expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); + expect(result).toContainPackage('d@1.0.0', atPath('a', 'node_modules', 'd')); + }); + test('can dedup and avoid circular reference', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture({ + 'a@1.0.0': ['c@1.0.0'], + 'b@2.0.0': [], + 'c@1.0.0': ['d@1.0.0'], + 'd@1.0.0': ['c@1.0.0'], + }); + + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['c']}; + + packageHoister.seed(['a@1.0.0', 'b@2.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(5); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@2.0.0', atPath('b')); + expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); + expect(result).toContainPackage('d@1.0.0', atPath('d')); + expect(result).toContainPackage('c@1.0.0', atPath('c')); + }); + test('can handle conflict version', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture({ + 'a@1.0.0': ['c@1.0.0'], + 'b@2.0.0': [], + 'b@1.0.0': [], + 'c@1.0.0': ['b@1.0.0'], + }); + + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['c']}; + + packageHoister.seed(['a@1.0.0', 'b@2.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(4); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@2.0.0', atPath('b')); + expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); + expect(result).toContainPackage('b@1.0.0', atPath('a', 'node_modules', 'b')); + }); + + test('nohoist matches package regardless version', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture({ + 'a@1.0.0': ['b@1.0.0', 'c@1.0.0'], + 'b@1.0.0': [], + 'b@2.0.0': [], + 'c@1.0.0': ['b@2.0.0'], + }); + + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['b', 'c']}; + + packageHoister.seed(['a@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(4); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@1.0.0', atPath('a', 'node_modules', 'b')); + expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); + expect(result).toContainPackage('b@2.0.0', atPath('a', 'node_modules', 'c', 'node_modules', 'b')); + }); + test('can detect circular reference', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture({ + 'a@1.0.0': ['b@1.0.0', 'c@1.0.0'], + 'b@2.0.0': [], + 'b@1.0.0': ['c@1.0.0'], + 'c@1.0.0': ['b@2.0.0'], + }); + + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['b']}; + + packageHoister.seed(['a@1.0.0', 'b@2.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(4); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@2.0.0', atPath('b')); + expect(result).toContainPackage('b@1.0.0', atPath('a', 'node_modules', 'b')); + expect(result).toContainPackage('c@1.0.0', atPath('c')); + }); + test('can nohoist a linked package', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture({ + 'a@1.0.0': ['b@1.0.0', 'c@1.0.0'], + 'b@1.0.0': ['d@1.0.0'], + 'c@1.0.0': [], + 'd@1.0.0': [], + }); + + // b is a linked package + let pkg: any = packageResolver.getStrictResolvedPattern('b@1.0.0'); + pkg._remote = {type: 'link'}; + + // a will not hoist b and everything under b + pkg = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['b', 'b/**']}; + + packageHoister.seed(['a@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(4); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('c@1.0.0', atPath('c')); + expect(result).toContainPackage('d@1.0.0', atPath('a', 'node_modules', 'd')); + expect(result).toContainPackage('b@1.0.0', atPath('a', 'node_modules', 'b')); + }); + + describe('nohoistList pattern matching', () => { + const paths = ['a', 'a/b', 'a/b/c', 'a/b/c/d', 'a/d', 'b/c', 'd/a', 'e/d/a', 'd/a/e', 'd/a/e/b']; + test('match explicit path', () => { + expect(mm(paths, 'a')).toEqual(['a']); + expect(mm(paths, 'b/c')).toEqual(['b/c']); + expect(mm(paths, 'd')).toEqual([]); + expect(mm(paths, 'a/b')).toEqual(['a/b']); + }); + test('match glob pattern', () => { + expect(mm(paths, '**')).toEqual(paths); + expect(mm(paths, '*')).toEqual(['a']); + + expect(mm(paths, 'a/*')).toEqual(['a/b', 'a/d']); + expect(mm(paths, 'a/**')).toEqual(['a/b', 'a/b/c', 'a/b/c/d', 'a/d']); + expect(mm(paths, '*/a')).toEqual(['d/a']); + expect(mm(paths, '**/a')).toEqual(['a', 'd/a', 'e/d/a']); + expect(mm(paths, '*/a/*')).toEqual(['d/a/e']); + expect(mm(paths, '**/a/**')).toEqual(['a/b', 'a/b/c', 'a/b/c/d', 'a/d', 'd/a/e', 'd/a/e/b']); + }); + }); + test('can disable hoist for the whole branch', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture({ + 'a@1.0.0': ['b@1.0.0', 'c@1.0.0'], + 'b@1.0.0': ['d@1.0.0'], + 'c@1.0.0': ['d@1.0.0'], + 'd@1.0.0': [], + }); + + // disable hoisting for everything under a + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['**']}; + + packageHoister.seed(['a@1.0.0', 'b@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(6); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('b@1.0.0', atPath('b')); + expect(result).toContainPackage('d@1.0.0', atPath('d')); + + expect(result).toContainPackage('b@1.0.0', atPath('a', 'node_modules', 'b')); + expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); + expect(result).toContainPackage('d@1.0.0', atPath('a', 'node_modules', 'd')); + }); + test('can disable hoist for particular package tree', () => { + const {atPath, packageHoister, packageResolver} = createTestFixture({ + 'a@1.0.0': ['b@1.0.0', 'e@1.0.0'], + 'b@1.0.0': ['c@1.0.0'], + 'c@1.0.0': ['d@1.0.0'], + 'd@1.0.0': [], + 'e@1.0.0': [], + }); + + // disable hoisting for everything under a + const pkg: any = packageResolver.getStrictResolvedPattern('a@1.0.0'); + pkg.workspaces = {nohoist: ['b', 'b/**']}; + + packageHoister.seed(['a@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(5); + expect(result).toContainPackage('a@1.0.0', atPath('a')); + expect(result).toContainPackage('e@1.0.0', atPath('e')); + + expect(result).toContainPackage('b@1.0.0', atPath('a', 'node_modules', 'b')); + expect(result).toContainPackage('c@1.0.0', atPath('a', 'node_modules', 'c')); + expect(result).toContainPackage('d@1.0.0', atPath('a', 'node_modules', 'd')); + }); + describe('nohoist with workspaces context', () => { + function updateWorkspaces(rootPattern: string, nohoist?: Array, workspaces: Array): UpdateResolver { + return (resolver: PackageResolver, config: Config): void => { + const root: Manifest = resolver.getStrictResolvedPattern(rootPattern); + if (nohoist) { + root.workspaces = {nohoist}; + } + + const wsMap: WorkspacesManifestMap = {}; + wsMap[root.name] = {loc: root._loc || '', manifest: root}; + + workspaces.forEach(w => { + const pkg = resolver.getStrictResolvedPattern(w); + pkg._remote = { + type: 'workspace', + registry: 'npm', + hash: null, + reference: '', + }; + wsMap[pkg.name] = {loc: pkg._loc || '', manifest: pkg}; + }); + resolver.workspaceLayout = new WorkspaceLayout(wsMap, config); + resolver.workspaceLayout.virtualManifestName = root.name; + + // hoister.nohoistResolver._wsRootPackageName = root.name; + }; + } + describe('disable hoist for a package', () => { + function fixture(f: UpdateResolver): any { + return createTestFixture( + { + 'w1@1.0.0': ['a@1.0.0'], + 'w2@1.0.0': ['a@1.0.0', 'b@1.0.0'], + 'a@1.0.0': ['c@1.0.0'], + 'b@1.0.0': ['a@1.0.0'], + 'c@1.0.0': [], + 'root@1.0.0': ['w1@1.0.0', 'w2@1.0.0'], + }, + true, + f, + ); + } + + test('from root for all workspaces', () => { + // root disable 'a' hoisting, no matter where it is + const {packageHoister} = fixture(updateWorkspaces('root@1.0.0', ['**/a'], ['w1@1.0.0', 'w2@1.0.0'])); + const config = packageHoister.config; + + packageHoister.seed(['root@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(8); + expect(result).toContainPackage('root@1.0.0', getPackagePath(config, 'root')); + expect(result).toContainPackage('w1@1.0.0', getPackagePath(config, 'w1')); + expect(result).toContainPackage('w2@1.0.0', getPackagePath(config, 'w2')); + expect(result).toContainPackage('b@1.0.0', getPackagePath(config, 'b')); + expect(result).toContainPackage('c@1.0.0', getPackagePath(config, 'c')); + + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'w1/a')); + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'w2/a')); + + // note: a hoisted b will also inherit the root's nohoist constraint + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'b/a')); + }); + test('from root for a specific workspaces', () => { + // root disable 'a' hoisting, no matter where it is + const {packageHoister} = fixture(updateWorkspaces('root@1.0.0', ['w1/a'], ['w1@1.0.0', 'w2@1.0.0'])); + const config = packageHoister.config; + + packageHoister.seed(['root@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(7); + expect(result).toContainPackage('root@1.0.0', getPackagePath(config, 'root')); + expect(result).toContainPackage('w1@1.0.0', getPackagePath(config, 'w1')); + expect(result).toContainPackage('w2@1.0.0', getPackagePath(config, 'w2')); + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'a')); + expect(result).toContainPackage('b@1.0.0', getPackagePath(config, 'b')); + expect(result).toContainPackage('c@1.0.0', getPackagePath(config, 'c')); + + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'w1/a')); + }); + test('from workspace', () => { + // w2 disable 'a' hoisting + const {packageHoister, packageResolver} = fixture( + updateWorkspaces('root@1.0.0', undefined, ['w1@1.0.0', 'w2@1.0.0']), + ); + const config = packageHoister.config; + + const pkg: any = packageResolver.getStrictResolvedPattern('w2@1.0.0'); + pkg.workspaces = {nohoist: ['a']}; + + packageHoister.seed(['root@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(7); + expect(result).toContainPackage('root@1.0.0', getPackagePath(config, 'root')); + expect(result).toContainPackage('w1@1.0.0', getPackagePath(config, 'w1')); + expect(result).toContainPackage('w2@1.0.0', getPackagePath(config, 'w2')); + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'a')); + expect(result).toContainPackage('b@1.0.0', getPackagePath(config, 'b')); + expect(result).toContainPackage('c@1.0.0', getPackagePath(config, 'c')); + + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'w2/a')); + }); + }); + describe('workspace depends on another workspace', () => { + function fixture(f: UpdateResolver): any { + return createTestFixture( + { + 'w1@1.0.0': ['a@1.0.0'], + 'w2@1.0.0': ['w1@1.0.0', 'b@1.0.0'], + 'a@1.0.0': ['c@1.0.0'], + 'b@1.0.0': ['c@1.0.0'], + 'c@1.0.0': [], + 'root@1.0.0': ['w1@1.0.0', 'w2@1.0.0'], + }, + true, + f, + ); + } + test('can nohoist dependent workspace just like any package', () => { + const {packageHoister, packageResolver} = fixture( + updateWorkspaces('root@1.0.0', undefined, ['w1@1.0.0', 'w2@1.0.0']), + ); + const config = packageHoister.config; + + // w2 disable 'w1' and all of w1's direct dependency hoisting + const pkg: any = packageResolver.getStrictResolvedPattern('w2@1.0.0'); + pkg.workspaces = {nohoist: ['w1', 'w1/**']}; + + packageHoister.seed(['root@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(9); + expect(result).toContainPackage('root@1.0.0', getPackagePath(config, 'root')); + expect(result).toContainPackage('w1@1.0.0', getPackagePath(config, 'w1')); + expect(result).toContainPackage('w2@1.0.0', getPackagePath(config, 'w2')); + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'a')); + expect(result).toContainPackage('b@1.0.0', getPackagePath(config, 'b')); + expect(result).toContainPackage('c@1.0.0', getPackagePath(config, 'c')); + + expect(result).toContainPackage('w1@1.0.0', getPackagePath(config, 'w2/w1')); + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'w2/a')); + expect(result).toContainPackage('c@1.0.0', getPackagePath(config, 'w2/c')); + }); + test('all workspaces nohoist will be honored', () => { + const {packageHoister, packageResolver} = fixture( + updateWorkspaces('root@1.0.0', undefined, ['w1@1.0.0', 'w2@1.0.0']), + ); + const config = packageHoister.config; + + // w2 disable all of its top level packages hoisting + let pkg: any = packageResolver.getStrictResolvedPattern('w2@1.0.0'); + pkg.workspaces = {nohoist: ['*']}; + + // w1 disable 'a' and all of its dependency hoisting + pkg = packageResolver.getStrictResolvedPattern('w1@1.0.0'); + pkg.workspaces = {nohoist: ['a', 'a/**']}; + + packageHoister.seed(['root@1.0.0']); + const result = packageHoister.init(); + + expect(result.length).toEqual(10); + // root + expect(result).toContainPackage('root@1.0.0', getPackagePath(config, 'root')); + expect(result).toContainPackage('w1@1.0.0', getPackagePath(config, 'w1')); + expect(result).toContainPackage('w2@1.0.0', getPackagePath(config, 'w2')); + // from w2/b/c + expect(result).toContainPackage('c@1.0.0', getPackagePath(config, 'c')); + + // under w1 + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'w1/a')); + expect(result).toContainPackage('c@1.0.0', getPackagePath(config, 'w1/c')); + + // under w2 + expect(result).toContainPackage('w1@1.0.0', getPackagePath(config, 'w2/w1')); + expect(result).toContainPackage('a@1.0.0', getPackagePath(config, 'w2/a')); + expect(result).toContainPackage('b@1.0.0', getPackagePath(config, 'w2/b')); + expect(result).toContainPackage('c@1.0.0', getPackagePath(config, 'w2/c')); + }); + }); + }); + test('originalParentPath shows before-hoist dependency tree path', () => { + const {packageHoister} = createTestFixture({ + 'a@1.0.0': ['c@1.0.0'], + 'b@1.0.0': ['c@1.0.0'], + 'c@1.0.0': [], + }); + + // disable hoisting for everything under a + packageHoister.seed(['a@1.0.0', 'b@1.0.0']); + const result = packageHoister.init(); + const paths = result.map(r => [r[1].key, r[1].originalParentPath]); + + expect(paths.length).toEqual(3); + expect(paths).toContainEqual(['a', '']); + expect(paths).toContainEqual(['b', '']); + expect(paths).toContainEqual(['c', '/a']); + }); + test('previousPaths should reflect hoist history', () => { + const {packageHoister} = createTestFixture({ + 'a@1.0.0': ['c@1.0.0'], + 'b@1.0.0': ['c@1.0.0'], + 'c@1.0.0': [], + }); + + // disable hoisting for everything under a + packageHoister.seed(['a@1.0.0', 'b@1.0.0']); + const result = packageHoister.init(); + const hoistHistory = result.map(r => [r[1].key, r[1].previousPaths]); + + expect(hoistHistory.length).toEqual(3); + expect(hoistHistory).toContainEqual(['a', []]); + expect(hoistHistory).toContainEqual(['b', []]); + expect(hoistHistory).toContainEqual(['c', ['/a/c', '/b/c']]); + }); +}); diff --git a/src/cli/commands/add.js b/src/cli/commands/add.js index f511d8e13b..5d14bc698c 100644 --- a/src/cli/commands/add.js +++ b/src/cli/commands/add.js @@ -21,7 +21,9 @@ import semver from 'semver'; export class Add extends Install { constructor(args: Array, flags: Object, config: Config, reporter: Reporter, lockfile: Lockfile) { - super(flags, config, reporter, lockfile); + const workspaceRootIsCwd = config.cwd === config.lockfileFolder; + const _flags = flags ? {...flags, workspaceRootIsCwd} : {workspaceRootIsCwd}; + super(_flags, config, reporter, lockfile); this.args = args; // only one flag is supported, so we can figure out which one was passed to `yarn add` this.flagToOrigin = [ @@ -104,6 +106,49 @@ export class Add extends Install { return preparedPatterns; } + preparePatternsForLinking(patterns: Array, cwdManifest: Manifest, cwdIsRoot: boolean): Array { + // remove the newly added patterns if cwd != root and update the in-memory package dependency instead + if (cwdIsRoot) { + return patterns; + } + + let manifest; + const cwdPackage = `${cwdManifest.name}@${cwdManifest.version}`; + try { + manifest = this.resolver.getStrictResolvedPattern(cwdPackage); + } catch (e) { + this.reporter.warn(this.reporter.lang('unknownPackage', cwdPackage)); + return patterns; + } + + let newPatterns = patterns; + this._iterateAddedPackages((pattern, registry, dependencyType, pkgName, version) => { + // remove added package from patterns list + const filtered = newPatterns.filter(p => p !== pattern); + invariant( + newPatterns.length - filtered.length > 0, + `expect added pattern '${pattern}' in the list: ${patterns.toString()}`, + ); + newPatterns = filtered; + + // add new package into in-memory manifest so they can be linked properly + manifest[dependencyType] = manifest[dependencyType] || {}; + if (manifest[dependencyType][pkgName] === version) { + // package already existed + return; + } + + // update dependencies in the manifest + invariant(manifest._reference, 'manifest._reference should not be null'); + const ref: Object = manifest._reference; + + ref['dependencies'] = ref['dependencies'] || []; + ref['dependencies'].push(pattern); + }); + + return newPatterns; + } + async bailout(patterns: Array, workspaceLayout: ?WorkspaceLayout): Promise { const lockfileCache = this.lockfile.cache; if (!lockfileCache) { @@ -154,7 +199,11 @@ export class Add extends Install { const opts: ListOptions = { reqDepth: 0, }; - const {trees, count} = await buildTree(this.resolver, this.linker, patterns, opts, true, true); + + // restore the original patterns + const merged = [...patterns, ...this.addedPatterns]; + + const {trees, count} = await buildTree(this.resolver, this.linker, merged, opts, true, true); this.reporter.success( count === 1 ? this.reporter.lang('savedNewDependency') : this.reporter.lang('savedNewDependencies', count), ); @@ -168,10 +217,28 @@ export class Add extends Install { async savePackages(): Promise { // fill rootPatternsToOrigin without `excludePatterns` await Install.prototype.fetchRequestFromCwd.call(this); - const patternOrigins = Object.keys(this.rootPatternsToOrigin); + // // get all the different registry manifests in this folder + const manifests: Object = await this.config.getRootManifests(); + + this._iterateAddedPackages((pattern, registry, dependencyType, pkgName, version) => { + // add it to manifest + const {object} = manifests[registry]; + + object[dependencyType] = object[dependencyType] || {}; + object[dependencyType][pkgName] = version; + + if (dependencyType !== this.flagToOrigin) { + this.reporter.warn(this.reporter.lang('moduleAlreadyInManifest', pkgName, dependencyType, this.flagToOrigin)); + } + }); + + await this.config.saveRootManifests(manifests); + } - // get all the different registry manifests in this folder - const manifests = await this.config.getRootManifests(); + _iterateAddedPackages( + f: (pattern: string, registry: string, dependencyType: string, pkgName: string, version: string) => void, + ) { + const patternOrigins = Object.keys(this.rootPatternsToOrigin); // add new patterns to their appropriate registry manifest for (const pattern of this.addedPatterns) { @@ -191,18 +258,8 @@ export class Add extends Install { // depType is calculated when `yarn upgrade` command is used const target = depType || this.flagToOrigin; - // add it to manifest - const {object} = manifests[ref.registry]; - - object[target] = object[target] || {}; - object[target][pkg.name] = version; - - if (target !== this.flagToOrigin) { - this.reporter.warn(this.reporter.lang('moduleAlreadyInManifest', pkg.name, depType, this.flagToOrigin)); - } + f(pattern, ref.registry, target, pkg.name, version); } - - await this.config.saveRootManifests(manifests); } } diff --git a/src/cli/commands/config.js b/src/cli/commands/config.js index e8340d0404..1e35326d73 100644 --- a/src/cli/commands/config.js +++ b/src/cli/commands/config.js @@ -31,6 +31,7 @@ const CONFIG_KEYS = [ 'childConcurrency', 'networkTimeout', 'workspacesEnabled', + 'workspacesNohoistEnabled', 'pruneOfflineMirror', 'enableMetaFolder', 'enableLockfileVersions', diff --git a/src/cli/commands/install.js b/src/cli/commands/install.js index a8a0f6c58a..118b739845 100644 --- a/src/cli/commands/install.js +++ b/src/cli/commands/install.js @@ -151,7 +151,7 @@ function normalizeFlags(config: Config, rawFlags: Object): Flags { // outdated, update-interactive includeWorkspaceDeps: !!rawFlags.includeWorkspaceDeps, - // remove, update + // add, remove, update workspaceRootIsCwd: rawFlags.workspaceRootIsCwd !== false, }; @@ -316,9 +316,11 @@ export class Install { } }; - pushDeps('dependencies', projectManifestJson, {hint: null, optional: false}, true); - pushDeps('devDependencies', projectManifestJson, {hint: 'dev', optional: false}, !this.config.production); - pushDeps('optionalDependencies', projectManifestJson, {hint: 'optional', optional: true}, true); + if (cwdIsRoot) { + pushDeps('dependencies', projectManifestJson, {hint: null, optional: false}, true); + pushDeps('devDependencies', projectManifestJson, {hint: 'dev', optional: false}, !this.config.production); + pushDeps('optionalDependencies', projectManifestJson, {hint: 'optional', optional: true}, true); + } if (this.config.workspaceRootFolder) { const workspaceLoc = cwdIsRoot ? loc : path.join(this.config.lockfileFolder, filename); @@ -356,6 +358,8 @@ export class Install { dependencies: workspaceDependencies, devDependencies: {...workspaceManifestJson.devDependencies}, optionalDependencies: {...workspaceManifestJson.optionalDependencies}, + private: workspaceManifestJson.private, + workspaces: workspaceManifestJson.workspaces, }; workspaceLayout.virtualManifestName = virtualDependencyManifest.name; const virtualDep = {}; @@ -397,6 +401,9 @@ export class Install { preparePatterns(patterns: Array): Array { return patterns; } + preparePatternsForLinking(patterns: Array, cwdManifest: Manifest, cwdIsRoot: boolean): Array { + return patterns; + } async bailout(patterns: Array, workspaceLayout: ?WorkspaceLayout): Promise { if (this.flags.skipIntegrityCheck || this.flags.force) { @@ -549,6 +556,11 @@ export class Install { // remove integrity hash to make this operation atomic await this.integrityChecker.removeIntegrityFile(); this.reporter.step(curr, total, this.reporter.lang('linkingDependencies'), emoji.get('link')); + flattenedTopLevelPatterns = this.preparePatternsForLinking( + flattenedTopLevelPatterns, + manifest, + this.config.lockfileFolder === this.config.cwd, + ); await this.linker.init(flattenedTopLevelPatterns, workspaceLayout, { linkDuplicates: this.flags.linkDuplicates, ignoreOptional: this.flags.ignoreOptional, diff --git a/src/cli/commands/why.js b/src/cli/commands/why.js index 73a6ff82d4..9d43c440f6 100644 --- a/src/cli/commands/why.js +++ b/src/cli/commands/why.js @@ -116,6 +116,15 @@ export function hasWrapper(commander: Object, args: Array): boolean { return true; } +// to conform to the current standard '#' as package tree separator +function toStandardPathString(pathString: string): string { + const str = pathString.replace(/\//g, '#'); + if (str[0] === '#') { + return str.slice(1); + } + return str; +} + export async function run(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { if (!args.length) { throw new MessageError(reporter.lang('missingWhyDependency')); @@ -143,124 +152,122 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg // finding reporter.step(3, 4, reporter.lang('whyFinding'), emoji.get('mag')); - let match; - for (const [loc, info] of hoisted) { - if (info.key === query || info.previousKeys.indexOf(query) >= 0) { - match = [loc, info]; - break; - } - } + const matches = queryWhy(query, hoisted); - if (!match) { + if (matches.length <= 0) { reporter.error(reporter.lang('whyUnknownMatch')); return; } - const [, matchInfo] = match; - const matchRef = matchInfo.pkg._reference; - invariant(matchRef, 'expected reference'); + const processMatch = async (match: HoistManifestTuple) => { + const [, matchInfo] = match; + const matchRef = matchInfo.pkg._reference; + invariant(matchRef, 'expected reference'); - const distinctMatchPatterns = new Set(matchRef.patterns); - const matchRequests = matchRef.requests; + const distinctMatchPatterns = new Set(matchRef.patterns); + const reasons = []; - const reasons = []; - // reason: dependency of these modules - for (const request of matchRequests) { - const parentRequest = request.parentRequest; - if (!parentRequest) { - continue; + // reason: dependency of these modules + if (matchInfo.originalParentPath.length > 0) { + reasons.push({ + type: 'whyDependedOn', + typeSimple: 'whyDependedOnSimple', + value: toStandardPathString(matchInfo.originalParentPath), + }); } - const dependent = install.resolver.getResolvedPattern(parentRequest.pattern); - if (!dependent) { - continue; + // reason: exists in manifest + let rootType; + for (const pattern of distinctMatchPatterns) { + rootType = install.rootPatternsToOrigin[pattern]; + if (rootType) { + reasons.push({ + type: 'whySpecified', + typeSimple: 'whySpecifiedSimple', + value: rootType, + }); + } } - const chain = []; - - let delegator = parentRequest; - do { - chain.push(install.resolver.getStrictResolvedPattern(delegator.pattern).name); - } while ((delegator = delegator.parentRequest)); - - reasons.push({ - type: 'whyDependedOn', - typeSimple: 'whyDependedOnSimple', - value: chain.reverse().join('#'), - }); - } - - // reason: exists in manifest - let rootType; - for (const pattern of distinctMatchPatterns) { - rootType = install.rootPatternsToOrigin[pattern]; - if (rootType) { + // reason: this is hoisted from these modules + for (const path of matchInfo.previousPaths) { reasons.push({ - type: 'whySpecified', - typeSimple: 'whySpecifiedSimple', - value: rootType, + type: 'whyHoistedFrom', + typeSimple: 'whyHoistedFromSimple', + value: toStandardPathString(path), }); } - } - // reason: this is hoisted from these modules - for (const pattern of matchInfo.previousKeys) { - if (pattern !== matchInfo.key) { + // package sizes + let packageSize = 0; + let directSizes = []; + let transitiveSizes = []; + try { + packageSize = await getPackageSize(match); + } catch (e) {} + + const dependencies = Array.from(collect(hoisted, new Set(), match)); + const transitiveDependencies = Array.from(collect(hoisted, new Set(), match, {recursive: true})); + + try { + directSizes = await Promise.all(dependencies.map(getPackageSize)); + transitiveSizes = await Promise.all(transitiveDependencies.map(getPackageSize)); + } catch (e) {} + + const transitiveKeys = new Set(transitiveDependencies.map(([, info]) => info.key)); + const sharedDependencies = getSharedDependencies(hoisted, transitiveKeys); + + // prepare output: populate reporter + reporter.info(reporter.lang('whyMatch', `${matchInfo.key}@${matchInfo.pkg.version}`)); + // + // reason: hoisted/nohoist + if (matchInfo.isNohoist) { reasons.push({ - type: 'whyHoistedFrom', - typeSimple: 'whyHoistedFromSimple', - value: pattern, + type: 'whyNotHoisted', + typeSimple: 'whyNotHoistedSimple', + value: matchInfo.nohoistList, }); + } else if (query === matchInfo.originalKey) { + reporter.info(reporter.lang('whyHoistedTo', matchInfo.key)); } - } - - // package sizes - reporter.step(4, 4, reporter.lang('whyCalculating'), emoji.get('aerial_tramway')); - let packageSize = 0; - let directSizes = []; - let transitiveSizes = []; - try { - packageSize = await getPackageSize(match); - } catch (e) {} + if (reasons.length === 1) { + reporter.info(reporter.lang(reasons[0].typeSimple, reasons[0].value)); + } else if (reasons.length > 1) { + reporter.info(reporter.lang('whyReasons')); + reporter.list('reasons', reasons.map(reason => reporter.lang(reason.type, reason.value))); + } else { + reporter.error(reporter.lang('whyWhoKnows')); + } - const dependencies = Array.from(collect(hoisted, new Set(), match)); - const transitiveDependencies = Array.from(collect(hoisted, new Set(), match, {recursive: true})); + if (packageSize) { + // stats: file size of this dependency without any dependencies + reporter.info(reporter.lang('whyDiskSizeWithout', bytes(packageSize))); - try { - directSizes = await Promise.all(dependencies.map(getPackageSize)); - transitiveSizes = await Promise.all(transitiveDependencies.map(getPackageSize)); - } catch (e) {} + // stats: file size of this dependency including dependencies that aren't shared + reporter.info(reporter.lang('whyDiskSizeUnique', bytes(packageSize + sum(directSizes)))); - const transitiveKeys = new Set(transitiveDependencies.map(([, info]) => info.key)); - const sharedDependencies = getSharedDependencies(hoisted, transitiveKeys); + // stats: file size of this dependency including dependencies + reporter.info(reporter.lang('whyDiskSizeTransitive', bytes(packageSize + sum(transitiveSizes)))); - // - // reason: hoisted - if (query === matchInfo.originalKey) { - reporter.info(reporter.lang('whyHoistedTo', matchInfo.key)); - } + // stats: shared transitive dependencies + reporter.info(reporter.lang('whySharedDependencies', sharedDependencies.size)); + } + }; - if (reasons.length === 1) { - reporter.info(reporter.lang(reasons[0].typeSimple, reasons[0].value)); - } else if (reasons.length > 1) { - reporter.info(reporter.lang('whyReasons')); - reporter.list('reasons', reasons.map(reason => reporter.lang(reason.type, reason.value))); - } else { - reporter.error(reporter.lang('whyWhoKnows')); + reporter.step(4, 4, reporter.lang('whyCalculating'), emoji.get('aerial_tramway')); + for (const match of matches) { + await processMatch(match); } +} - if (packageSize) { - // stats: file size of this dependency without any dependencies - reporter.info(reporter.lang('whyDiskSizeWithout', bytes(packageSize))); - - // stats: file size of this dependency including dependencies that aren't shared - reporter.info(reporter.lang('whyDiskSizeUnique', bytes(packageSize + sum(directSizes)))); - - // stats: file size of this dependency including dependencies - reporter.info(reporter.lang('whyDiskSizeTransitive', bytes(packageSize + sum(transitiveSizes)))); - - // stats: shared transitive dependencies - reporter.info(reporter.lang('whySharedDependencies', sharedDependencies.size)); +export function queryWhy(pattern: string, hoisted: HoistManifestTuples): Array { + const nohoistPattern = `#${pattern}`; + const found: Array = []; + for (const [loc, info] of hoisted) { + if (info.key === pattern || info.previousPaths.indexOf(pattern) >= 0 || info.key.endsWith(nohoistPattern)) { + found.push([loc, info]); + } } + return found; } diff --git a/src/config.js b/src/config.js index d59ad58b68..0b989b45a0 100644 --- a/src/config.js +++ b/src/config.js @@ -2,7 +2,7 @@ import type {RegistryNames, ConfigRegistries} from './registries/index.js'; import type {Reporter} from './reporters/index.js'; -import type {Manifest, PackageRemote, WorkspacesManifestMap} from './types.js'; +import type {Manifest, PackageRemote, WorkspacesManifestMap, WorkspacesConfig} from './types.js'; import type PackageReference from './package-reference.js'; import {execFromManifest} from './util/execute-lifecycle-script.js'; import {resolveWithHome} from './util/path.js'; @@ -156,6 +156,7 @@ export default class Config { nonInteractive: boolean; workspacesEnabled: boolean; + workspacesNohoistEnabled: boolean; // cwd: string; @@ -321,6 +322,7 @@ export default class Config { this._cacheRootFolder = String(cacheRootFolder); } this.workspacesEnabled = this.getOption('workspaces-experimental') !== false; + this.workspacesNohoistEnabled = this.getOption('workspaces-nohoist-experimental') !== false; this.pruneOfflineMirror = Boolean(this.getOption('yarn-offline-mirror-pruning')); this.enableMetaFolder = Boolean(this.getOption('enable-meta-folder')); @@ -615,9 +617,10 @@ export default class Config { do { const manifest = await this.findManifest(current, true); - if (manifest && manifest.workspaces) { + const ws = extractWorkspaces(manifest); + if (ws && ws.packages) { const relativePath = path.relative(current, initial); - if (relativePath === '' || micromatch([relativePath], manifest.workspaces).length > 0) { + if (relativePath === '' || micromatch([relativePath], ws.packages).length > 0) { return current; } else { return null; @@ -633,13 +636,13 @@ export default class Config { async resolveWorkspaces(root: string, rootManifest: Manifest): Promise { const workspaces = {}; - const patterns = rootManifest.workspaces || []; if (!this.workspacesEnabled) { return workspaces; } - if (!rootManifest.private && patterns.length > 0) { - throw new MessageError(this.reporter.lang('workspacesRequirePrivateProjects')); - } + + const ws = this.getWorkspaces(rootManifest, true); + const patterns = ws && ws.packages ? ws.packages : []; + if (!Array.isArray(patterns)) { throw new MessageError(this.reporter.lang('workspacesSettingMustBeArray')); } @@ -686,6 +689,49 @@ export default class Config { return workspaces; } + // workspaces functions + getWorkspaces(manifest: ?Manifest, shouldThrow: boolean = false): ?WorkspacesConfig { + if (!manifest || !this.workspacesEnabled) { + return undefined; + } + + const ws = extractWorkspaces(manifest); + + if (!ws) { + return ws; + } + + // validate eligibility + let wsCopy = {...ws}; + const warnings: Array = []; + + // packages + if (wsCopy.packages && wsCopy.packages.length > 0 && !manifest.private) { + warnings.push(this.reporter.lang('workspacesRequirePrivateProjects')); + wsCopy = undefined; + } + // nohoist + if (wsCopy && wsCopy.nohoist && wsCopy.nohoist.length > 0) { + if (!this.workspacesNohoistEnabled) { + warnings.push(this.reporter.lang('workspacesNohoistDisabled', manifest.name)); + wsCopy.nohoist = undefined; + } else if (!manifest.private) { + warnings.push(this.reporter.lang('workspacesNohoistRequirePrivatePackages', manifest.name)); + wsCopy.nohoist = undefined; + } + } + + if (warnings.length > 0) { + const msg = warnings.join('\n'); + if (shouldThrow) { + throw new MessageError(msg); + } else { + this.reporter.warn(msg); + } + } + return wsCopy; + } + /** * Description */ @@ -769,3 +815,22 @@ export default class Config { return config; } } + +export function extractWorkspaces(manifest: ?Manifest): ?WorkspacesConfig { + if (!manifest || !manifest.workspaces) { + return undefined; + } + + if (Array.isArray(manifest.workspaces)) { + return {packages: manifest.workspaces}; + } + + if ( + (manifest.workspaces.packages && Array.isArray(manifest.workspaces.packages)) || + (manifest.workspaces.nohoist && Array.isArray(manifest.workspaces.nohoist)) + ) { + return manifest.workspaces; + } + + return undefined; +} diff --git a/src/package-hoister.js b/src/package-hoister.js index 3ac70dc57c..f8c2a00c5a 100644 --- a/src/package-hoister.js +++ b/src/package-hoister.js @@ -1,9 +1,10 @@ /* @flow */ import type PackageResolver from './package-resolver.js'; -import type Config from './config.js'; +import Config from './config.js'; import type {Manifest} from './types.js'; import {sortAlpha} from './util/misc.js'; +import mm from 'micromatch'; const invariant = require('invariant'); const path = require('path'); @@ -12,6 +13,12 @@ type Parts = Array; let historyCounter = 0; +const LINK_TYPES = new Set(['workspace', 'link']); +type NewPartsType = { + parts: Parts, + duplicate: boolean, +}; + export class HoistManifest { constructor( key: string, @@ -31,10 +38,13 @@ export class HoistManifest { this.key = key; this.parts = parts; this.originalKey = key; - this.previousKeys = []; + this.previousPaths = []; this.history = []; this.addHistory(`Start position = ${key}`); + + this.isNohoist = false; + this.originalParentPath = ''; } isRequired: boolean; @@ -43,11 +53,16 @@ export class HoistManifest { pkg: Manifest; loc: string; parts: Parts; - previousKeys: Array; + previousPaths: Array; history: Array; key: string; originalKey: string; + // nohoist info + isNohoist: boolean; + nohoistList: ?Array; + originalParentPath: string; + addHistory(msg: string) { this.history.push(`${++historyCounter}: ${msg}`); } @@ -63,10 +78,13 @@ export default class PackageHoister { this.taintedKeys = new Map(); this.levelQueue = []; this.tree = new Map(); + + this.nohoistResolver = new NohoistResolver(config, resolver); } resolver: PackageResolver; config: Config; + nohoistResolver: NohoistResolver; ignoreOptional: ?boolean; @@ -202,7 +220,9 @@ export default class PackageHoister { const parts = parentParts.concat(pkg.name); const key: string = this.implodeKey(parts); const info: HoistManifest = new HoistManifest(key, parts, pkg, loc, isDirectRequire, isRequired, isIncompatible); - // + + this.nohoistResolver.initNohoist(info, parent); + this.tree.set(key, info); this.taintKey(key, info); @@ -216,7 +236,7 @@ export default class PackageHoister { /** * Propagate inherited ignore statuses from non-ignored to ignored packages - */ + */ _propagateRequired() { // @@ -254,7 +274,7 @@ export default class PackageHoister { /** * Looks up the package a dependency resolves to - */ + */ _lookupDependency(info: HoistManifest, depPattern: string): ?HoistManifest { // @@ -279,21 +299,19 @@ export default class PackageHoister { * Find the highest position we can hoist this module to. */ - getNewParts( - key: string, - info: HoistManifest, - parts: Parts, - ): { - parts: Parts, - duplicate: boolean, - } { + getNewParts(key: string, info: HoistManifest, parts: Parts): NewPartsType { let stepUp = false; + const highestHoistingPoint = this.nohoistResolver.highestHoistingPoint(info) || 0; const fullKey = this.implodeKey(parts); const stack = []; // stack of removed parts const name = parts.pop(); - for (let i = parts.length - 1; i >= 0; i--) { + if (info.isNohoist) { + info.addHistory(`Marked as nohoist, will not be hoisted above '${parts[highestHoistingPoint]}'`); + } + + for (let i = parts.length - 1; i >= highestHoistingPoint; i--) { const checkParts = parts.slice(0, i).concat(name); const checkKey = this.implodeKey(checkParts); info.addHistory(`Looked at ${checkKey} for a match`); @@ -328,7 +346,7 @@ export default class PackageHoister { const peerDependencies = Object.keys(info.pkg.peerDependencies || {}); // remove redundant parts that wont collide - hoistLoop: while (parts.length) { + hoistLoop: while (parts.length > highestHoistingPoint) { // we must not hoist a package higher than its peer dependencies for (const peerDependency of peerDependencies) { const checkParts = parts.concat(peerDependency); @@ -369,6 +387,10 @@ export default class PackageHoister { // const isValidPosition = (parts: Parts): boolean => { + // nohoist package can't be hoisted to the "root" + if (parts.length <= highestHoistingPoint) { + return false; + } const key = this.implodeKey(parts); const existing = this.tree.get(key); if (existing && existing.loc === info.loc) { @@ -415,18 +437,19 @@ export default class PackageHoister { // remove this item from the `tree` map so we can ignore it this.tree.delete(oldKey); - const {parts, duplicate} = this.getNewParts(oldKey, info, rawParts.slice()); + const newKey = this.implodeKey(parts); if (duplicate) { info.addHistory(`Satisfied from above by ${newKey}`); this.declareRename(info, rawParts, parts); + this.updateHoistHistory(this.nohoistResolver._originalPath(info), this.implodeKey(parts)); return; } // update to the new key if (oldKey === newKey) { - info.addHistory("Didn't hoist - conflicts above"); + info.addHistory(`Didn't hoist - see reason above`); this.setKey(info, oldKey, rawParts); return; } @@ -460,6 +483,12 @@ export default class PackageHoister { } } + updateHoistHistory(fromPath: string, toKey: string) { + const info = this.tree.get(toKey); + invariant(info, `expect to find hoist-to ${toKey}`); + info.previousPaths.push(fromPath); + } + /** * Update the key of a module and update our references. */ @@ -475,7 +504,9 @@ export default class PackageHoister { return; } - info.previousKeys.push(newKey); + const fromInfo = this.tree.get(newKey); + invariant(fromInfo, `expect to find hoist-from ${newKey}`); + info.previousPaths.push(this.nohoistResolver._originalPath(fromInfo)); info.addHistory(`New position = ${newKey}`); } @@ -660,5 +691,105 @@ export default class PackageHoister { } } +const WS_ROOT_ALIAS = '_project_'; +export class NohoistResolver { + constructor(config: Config, resolver: PackageResolver) { + this._resolver = resolver; + this._config = config; + if (resolver.workspaceLayout) { + this._wsRootPackageName = resolver.workspaceLayout.virtualManifestName; + const {manifest} = resolver.workspaceLayout.getWorkspaceManifest(this._wsRootPackageName); + this._wsRootNohoistList = this._extractNohoistList(manifest, manifest.name); + } + } + _resolver: PackageResolver; + _config: Config; + _wsRootNohoistList: ?Array; + _wsRootPackageName: ?string; + + /** + * examine the top level packages to find the root package + */ + initNohoist = (info: HoistManifest, parent: ?HoistManifest) => { + let parentNohoistList: ?Array; + let originalParentPath: string = info.originalParentPath; + + if (parent) { + parentNohoistList = parent.nohoistList; + originalParentPath = this._originalPath(parent); + } else { + invariant(this._isTopPackage(info), `${info.key} doesn't have parent nor a top package`); + if (info.pkg.name !== this._wsRootPackageName) { + parentNohoistList = this._wsRootNohoistList; + originalParentPath = this._wsRootPackageName || ''; + } + } + + info.originalParentPath = originalParentPath; + let nohoistList = this._extractNohoistList(info.pkg, this._originalPath(info)) || []; + if (parentNohoistList) { + nohoistList = nohoistList.concat(parentNohoistList); + } + info.nohoistList = nohoistList.length > 0 ? nohoistList : null; + info.isNohoist = this._isNohoist(info); + }; + + /** + * find the highest hoisting point for the given HoistManifest. + * algorithm: a nohoist package should never be hoisted beyond the top of its branch, i.e. + * the first element of its parts. Therefore the highest possible hoisting index is 1, + * unless the package has only 1 part (itself), in such case returns null just like any hoisted package + * + */ + + highestHoistingPoint = (info: HoistManifest): ?number => { + return info.isNohoist && info.parts.length > 1 ? 1 : null; + }; + + // private functions + _isNohoist = (info: HoistManifest): boolean => { + if (!info.nohoistList || info.nohoistList.length <= 0) { + return false; + } + const path = this._originalPath(info); + + // top package can not be marked 'nohoist' because it is already at the top (hoisted). + return !this._isTopPackage(info) && mm.any(path, info.nohoistList); + }; + _isRootPackage = (pkg: Manifest): boolean => { + return pkg.name === this._wsRootPackageName; + }; + _originalPath = (info: HoistManifest): string => { + return this._makePath(info.originalParentPath, info.pkg.name); + }; + _makePath(...args: Array): string { + const parts = args.map(s => (s === this._wsRootPackageName ? WS_ROOT_ALIAS : s)); + return parts.join('/'); + } + _isTopPackage = (info: HoistManifest): boolean => { + const parentParts = info.parts.slice(0, -1); + const result = + !parentParts || + parentParts.length <= 0 || + (parentParts.length === 1 && parentParts[0] === this._wsRootPackageName); + return result; + }; + _isLink = (info: HoistManifest): boolean => { + return info.pkg._remote != null && LINK_TYPES.has(info.pkg._remote.type); + }; + + // extract nohoist from package.json then prefix them with branch path + // so we can matched against the branch tree ("originalPath") later + _extractNohoistList = (pkg: Manifest, pathPrefix: string): ?Array => { + let nohoistList: ?Array; + const ws = this._config.getWorkspaces(pkg); + + if (ws && ws.nohoist) { + nohoistList = ws.nohoist.map(p => this._makePath(pathPrefix, p)); + } + return nohoistList; + }; +} + export type HoistManifestTuple = [string, HoistManifest]; export type HoistManifestTuples = Array; diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index af1bcba6b9..87c9e05a0b 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -185,6 +185,11 @@ const messages = { workspacesSettingMustBeArray: 'The workspaces field in package.json must be an array.', workspacesDisabled: 'Your project root defines workspaces but the feature is disabled in your Yarn config. Please check "workspaces-experimental" in your .yarnrc file.', + + workspacesNohoistRequirePrivatePackages: + 'nohoist config is ignored in $0 because it is not a private package. If you think nohoist should be allowed in public packages, please submit an issue for your use case.', + workspacesNohoistDisabled: `$0 defines nohoist but the feature is disabled in your Yarn config. Please check "workspaces-nohoist-experimental" in your .yarnrc file.`, + workspaceRootNotFound: "Cannot find the root of your workspace - are you sure you're currently in a workspace?", workspaceMissingWorkspace: 'Missing workspace name.', workspaceMissingCommand: 'Missing command name.', @@ -273,13 +278,17 @@ const messages = { whyHoistedTo: `Has been hoisted to $0`, whyHoistedFromSimple: `This module exists because it's hoisted from $0.`, + whyNotHoistedSimple: `This module exists here because it's in the nohoist list $0.`, whyDependedOnSimple: `This module exists because $0 depends on it.`, whySpecifiedSimple: `This module exists because it's specified in $0.`, whyReasons: 'Reasons this module exists', whyHoistedFrom: 'Hoisted from $0', + whyNotHoisted: `in the nohoist list $0`, whyDependedOn: '$0 depends on it', whySpecified: `Specified in $0`, + whyMatch: `\r=> Found $0`, + uninstalledPackages: 'Uninstalled packages.', uninstallRegenerate: 'Regenerating lockfile and installing missing dependencies', diff --git a/src/types.js b/src/types.js index 1f5a800617..7d267d1c29 100644 --- a/src/types.js +++ b/src/types.js @@ -48,6 +48,11 @@ type Dependencies = { [key: string]: string, }; +export type WorkspacesConfig = { + packages?: Array, + nohoist?: Array, +}; + // package.json export type Manifest = { _registry?: ?RegistryNames, @@ -130,7 +135,7 @@ export type Manifest = { files?: Array, main?: string, - workspaces?: Array, + workspaces?: Array | WorkspacesConfig, // This flag is true when we add a new package with `yarn add `. // We need to preserve the flag because we print a list of new packages in From 6dbc9d7b4af6db4d2460f5abb18fdd207a3417a5 Mon Sep 17 00:00:00 2001 From: Michael Jungo Date: Mon, 29 Jan 2018 17:33:46 +0100 Subject: [PATCH 28/34] fix(cli): Use correct directory for upgrade-interactive (#5272) --- src/cli/commands/upgrade-interactive.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cli/commands/upgrade-interactive.js b/src/cli/commands/upgrade-interactive.js index f106f4f23a..090341f53a 100644 --- a/src/cli/commands/upgrade-interactive.js +++ b/src/cli/commands/upgrade-interactive.js @@ -169,13 +169,17 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg acc[workspaceLoc] = xs.concat(dep); return acc; }, {}); + const cwd = config.cwd; for (const loc of Object.keys(depsByWorkspace)) { const patterns = depsByWorkspace[loc].map(getPattern); cleanLockfile(lockfile, deps, packagePatterns, reporter); reporter.info(reporter.lang('updateInstalling', getNameFromHint(hint))); - config.cwd = path.resolve(path.dirname(loc)); + if (loc !== '') { + config.cwd = path.resolve(path.dirname(loc)); + } const add = new Add(patterns, flags, config, reporter, lockfile); await add.init(); + config.cwd = cwd; } } } From 328fd596de935acc6c3e134741748fcc62ec3739 Mon Sep 17 00:00:00 2001 From: Gord P Date: Mon, 29 Jan 2018 11:39:26 -0500 Subject: [PATCH 29/34] Allow scoped package as alias source (#5229) **Summary** Yarn already supports aliasing a scoped package with an unscoped package: ```bash yarn add @goodforonefare/left-pad@npm:left-pad@1.2.0 ``` This PR adds support for aliasing any package with a scoped package: ```bash yarn add left-pad@npm:@goodforonefare/left-pad@1.2.0 ``` Note: the only documentation I can find for this feature [is a tweet from Sebastian McKenzie](https://twitter.com/sebmck/status/873958247304232961?lang=en). **Test plan** * `cd` to a yarn-managed repo * Add a scoped alias for `left-pad`: * `yarn add left-pad@npm:@goodforonefare/left-pad` * Verify that `left-pad` calls append my username to inputs: ``` $ node -e "console.log(require('left-pad')('test', 20))"` GoodForOneFare test ``` --- .../resolvers/exotics/registry-resolver.js | 30 +++++++++++++++++++ src/resolvers/exotics/registry-resolver.js | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 __tests__/resolvers/exotics/registry-resolver.js diff --git a/__tests__/resolvers/exotics/registry-resolver.js b/__tests__/resolvers/exotics/registry-resolver.js new file mode 100644 index 0000000000..ab8d802594 --- /dev/null +++ b/__tests__/resolvers/exotics/registry-resolver.js @@ -0,0 +1,30 @@ +/* @flow */ + +import PackageRequest from '../../../src/package-request.js'; +import RegistryResolver from '../../../src/resolvers/exotics/registry-resolver.js'; + +const mockPackageRequest: PackageRequest = ({}: any); + +test('resolves unscoped npm: package', () => { + const resolver = new RegistryResolver(mockPackageRequest, 'npm:foo@0.0.1'); + + expect(resolver.name).toEqual('foo'); +}); + +test('resolves scoped npm: package', () => { + const resolver = new RegistryResolver(mockPackageRequest, 'npm:@org/foo@0.0.1'); + + expect(resolver.name).toEqual('@org/foo'); +}); + +test('resolves unscoped yarn: package', () => { + const resolver = new RegistryResolver(mockPackageRequest, 'yarn:foo@0.0.1'); + + expect(resolver.name).toEqual('foo'); +}); + +test('resolves scoped yarn: package', () => { + const resolver = new RegistryResolver(mockPackageRequest, 'yarn:@org/foo@0.0.1'); + + expect(resolver.name).toEqual('@org/foo'); +}); diff --git a/src/resolvers/exotics/registry-resolver.js b/src/resolvers/exotics/registry-resolver.js index a8c3437e73..f75f673e86 100644 --- a/src/resolvers/exotics/registry-resolver.js +++ b/src/resolvers/exotics/registry-resolver.js @@ -9,7 +9,7 @@ export default class RegistryResolver extends ExoticResolver { constructor(request: PackageRequest, fragment: string) { super(request, fragment); - const match = fragment.match(/^(\S+):(.*?)(@(.*?)|)$/); + const match = fragment.match(/^(\S+):(@?.*?)(@(.*?)|)$/); if (match) { this.range = match[4] || 'latest'; this.name = match[2]; From 18ea344707694a02987f111e3d32085893437d9f Mon Sep 17 00:00:00 2001 From: Gabriel Aumala Date: Mon, 29 Jan 2018 11:55:54 -0500 Subject: [PATCH 30/34] feat: better error when package is not found (#5213) When a package is not found during installation, show which package is requiring it (if any) in the error message. If there is no parent request, throw the same error as before. Add new localized string 'requiredPackageNotFoundRegistry' which is the same 'packageNotFoundRegistry', but includes the parent package pattern. --- src/package-request.js | 13 ++++++++++++- src/reporters/lang/en.js | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/package-request.js b/src/package-request.js index 3f6f747b6a..e2ae710dbd 100644 --- a/src/package-request.js +++ b/src/package-request.js @@ -111,7 +111,18 @@ export default class PackageRequest { const Resolver = this.getRegistryResolver(); const resolver = new Resolver(this, name, range); - return resolver.resolve(); + try { + return await resolver.resolve(); + } catch (err) { + // if it is not an error thrown by yarn and it has a parent request, + // thow a more readable error + if (!(err instanceof MessageError) && this.parentRequest && this.parentRequest.pattern) { + throw new MessageError( + this.reporter.lang('requiredPackageNotFoundRegistry', pattern, this.parentRequest.pattern, this.registry), + ); + } + throw err; + } } /** diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index 87c9e05a0b..c42ecdea95 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -80,6 +80,7 @@ const messages = { invalidVersion: 'Invalid version supplied.', requiredVersionInRange: 'Required version in range.', packageNotFoundRegistry: "Couldn't find package $0 on the $1 registry.", + requiredPackageNotFoundRegistry: "Couldn't find package $0 required by $1 on the $2 registry.", doesntExist: "Package $1 refers to a non-existing file '$0'.", missingRequiredPackageKey: `Package $0 doesn't have a $1.`, invalidAccess: 'Invalid argument for access, expected public or restricted.', From 06103bda963071eb6476a662cfdb159b407987e3 Mon Sep 17 00:00:00 2001 From: Maciej Kasprzyk Date: Mon, 29 Jan 2018 17:58:01 +0100 Subject: [PATCH 31/34] feat(cli): error on missing workspace directory (#5206) (#5222) --- __tests__/commands/add.js | 6 +++--- src/config.js | 3 +++ src/reporters/lang/en.js | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/__tests__/commands/add.js b/__tests__/commands/add.js index d9cdde7e3a..1d01301a39 100644 --- a/__tests__/commands/add.js +++ b/__tests__/commands/add.js @@ -95,14 +95,14 @@ test.concurrent('adds any new package to the current workspace, but install from expect(await fs.exists(`${config.cwd}/yarn.lock`)).toEqual(true); expect(await fs.exists(`${config.cwd}/packages/package-b/yarn.lock`)).toEqual(false); - await add(await makeConfigFromDirectory(`${config.cwd}/non-packages/package-c`, reporter), reporter, {}, [ + await add(await makeConfigFromDirectory(`${config.cwd}/non-package/package-c`, reporter), reporter, {}, [ 'isarray', ]); expect(await fs.exists(`${config.cwd}/node_modules/isarray`)).toEqual(false); - expect(await fs.exists(`${config.cwd}/non-packages/package-c/node_modules/isarray`)).toEqual(true); + expect(await fs.exists(`${config.cwd}/non-package/package-c/node_modules/isarray`)).toEqual(true); - expect(await fs.exists(`${config.cwd}/non-packages/package-c/yarn.lock`)).toEqual(true); + expect(await fs.exists(`${config.cwd}/non-package/package-c/yarn.lock`)).toEqual(true); }); }); diff --git a/src/config.js b/src/config.js index 0b989b45a0..071beec009 100644 --- a/src/config.js +++ b/src/config.js @@ -614,6 +614,9 @@ export default class Config { async findWorkspaceRoot(initial: string): Promise { let previous = null; let current = path.normalize(initial); + if (!await fs.exists(current)) { + throw new MessageError(this.reporter.lang('folderMissing', current)); + } do { const manifest = await this.findManifest(current, true); diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index c42ecdea95..dfaa37c0ee 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -385,6 +385,7 @@ const messages = { verboseUpgradeBecauseOutdated: 'Considering upgrade of $0 to $1 because a newer version exists in the registry.', verboseUpgradeNotUnlocking: 'Not unlocking $0 in the lockfile because it is a new or direct dependency.', verboseUpgradeUnlocking: 'Unlocking $0 in the lockfile.', + folderMissing: "Directory $0 doesn't exist", }; export type LanguageKeys = $Keys; From aa855c5c59334762be559956b042b053fdd1ace2 Mon Sep 17 00:00:00 2001 From: kaylieEB Date: Tue, 30 Jan 2018 13:07:39 +0100 Subject: [PATCH 32/34] fix(CLI): Use process exit instead of exitCode for node < 4 (#5291) * fix(CLI): Use process exit instead of exitCode Since node 0.10 doesn't support process.exitCode, use process.exit * lint --- bin/yarn.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/yarn.js b/bin/yarn.js index 0ff0839bf9..e46b1f6002 100755 --- a/bin/yarn.js +++ b/bin/yarn.js @@ -9,7 +9,7 @@ var majorVer = parseInt(ver.split('.')[0], 10); if (majorVer < 4) { console.error('Node version ' + ver + ' is not supported, please use Node.js 4.0 or higher.'); - process.exitCode = 1; + process.exit(1); // eslint-disable-line no-process-exit } else { var dirPath = '../lib/'; var v8CompileCachePath = dirPath + 'v8-compile-cache'; From aa200e4d63f8720738ca4c07bd5a38c2f89a402f Mon Sep 17 00:00:00 2001 From: Jeff Valore Date: Tue, 30 Jan 2018 07:08:31 -0500 Subject: [PATCH 33/34] feat(publish): Publish command uses publishConfig.access in package.json (#5290) * feat(publish): Publish command uses publishConfig.access in package.json For npm compatability, `yarn publish` should check `publishConfig.access` in package.json and use it as if the `--access` option was passed. #5279 * WIP: CI test failure debugging * WIP: CI test failure debugging * WIP: CI test failure debugging * fix CI errors by mocking npm password prompt * use jest expect().toBeCalledWith() for publish command tests --- __tests__/__mocks__/npm-registry.js | 10 ++ __tests__/commands/publish.js | 101 ++++++++++++++++++ .../fixtures/publish/minimal/package.json | 4 + .../fixtures/publish/public/package.json | 7 ++ src/cli/commands/publish.js | 11 +- 5 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 __tests__/__mocks__/npm-registry.js create mode 100644 __tests__/commands/publish.js create mode 100644 __tests__/fixtures/publish/minimal/package.json create mode 100644 __tests__/fixtures/publish/public/package.json diff --git a/__tests__/__mocks__/npm-registry.js b/__tests__/__mocks__/npm-registry.js new file mode 100644 index 0000000000..c5f54cb2a7 --- /dev/null +++ b/__tests__/__mocks__/npm-registry.js @@ -0,0 +1,10 @@ +/* @flow */ + +import Registry from '../../src/registries/base-registry.js'; +import type {RegistryRequestOptions} from '../../src/registries/base-registry.js'; + +export default class NpmRegistry extends Registry { + request(pathname: string, opts?: RegistryRequestOptions = {}, packageName: ?string): Promise<*> { + return new Promise(resolve => resolve()); + } +} diff --git a/__tests__/commands/publish.js b/__tests__/commands/publish.js new file mode 100644 index 0000000000..aaee892112 --- /dev/null +++ b/__tests__/commands/publish.js @@ -0,0 +1,101 @@ +/* @flow */ + +import {run as buildRun} from './_helpers.js'; +import {run as publish} from '../../src/cli/commands/publish.js'; +import {ConsoleReporter} from '../../src/reporters/index.js'; + +const path = require('path'); + +const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'publish'); + +const setupMocks = function(config) { + // Mock actual network request so that no package is actually published. + // $FlowFixMe + config.registries.npm.request = jest.fn(); + config.registries.npm.request.mockReturnValue( + new Promise(resolve => { + resolve({status: 200}); + }), + ); + + // Mock the npm login name. Otherwise yarn will prompt for it and break CI. + // $FlowFixMe + config.registries.npm.getAuth = jest.fn(); + config.registries.npm.getAuth.mockReturnValue('test'); +}; + +const runPublish = buildRun.bind( + null, + ConsoleReporter, + fixturesLoc, + async (args, flags, config, reporter, lockfile, getStdout): Promise => { + setupMocks(config); + await publish(config, reporter, flags, args); + return getStdout(); + }, +); + +test.concurrent('publish should default access to undefined', () => { + return runPublish([], {newVersion: '0.0.1'}, 'minimal', config => { + expect(config.registries.npm.request).toBeCalledWith( + expect.any(String), + expect.objectContaining({ + body: expect.objectContaining({ + access: undefined, + }), + }), + ); + }); +}); + +test.concurrent('publish should accept `--access restricted` argument', () => { + return runPublish([], {newVersion: '0.0.1', access: 'restricted'}, 'minimal', config => { + expect(config.registries.npm.request).toBeCalledWith( + expect.any(String), + expect.objectContaining({ + body: expect.objectContaining({ + access: 'restricted', + }), + }), + ); + }); +}); + +test.concurrent('publish should accept `--access public` argument', () => { + return runPublish([], {newVersion: '0.0.1', access: 'public'}, 'minimal', config => { + expect(config.registries.npm.request).toBeCalledWith( + expect.any(String), + expect.objectContaining({ + body: expect.objectContaining({ + access: 'public', + }), + }), + ); + }); +}); + +test.concurrent('publish should use publishConfig.access in package manifest', () => { + return runPublish([], {newVersion: '0.0.1'}, 'public', config => { + expect(config.registries.npm.request).toBeCalledWith( + expect.any(String), + expect.objectContaining({ + body: expect.objectContaining({ + access: 'public', + }), + }), + ); + }); +}); + +test.concurrent('publish should allow `--access` to override publishConfig.access', () => { + return runPublish([], {newVersion: '0.0.1', access: 'restricted'}, 'public', config => { + expect(config.registries.npm.request).toBeCalledWith( + expect.any(String), + expect.objectContaining({ + body: expect.objectContaining({ + access: 'restricted', + }), + }), + ); + }); +}); diff --git a/__tests__/fixtures/publish/minimal/package.json b/__tests__/fixtures/publish/minimal/package.json new file mode 100644 index 0000000000..1545befa16 --- /dev/null +++ b/__tests__/fixtures/publish/minimal/package.json @@ -0,0 +1,4 @@ +{ + "name": "test", + "version": "0.0.0" +} diff --git a/__tests__/fixtures/publish/public/package.json b/__tests__/fixtures/publish/public/package.json new file mode 100644 index 0000000000..0de9c86d5d --- /dev/null +++ b/__tests__/fixtures/publish/public/package.json @@ -0,0 +1,7 @@ +{ + "name": "test", + "version": "0.0.0", + "publishConfig": { + "access": "public" + } +} diff --git a/src/cli/commands/publish.js b/src/cli/commands/publish.js index ee16431e4b..d53ed1ebe7 100644 --- a/src/cli/commands/publish.js +++ b/src/cli/commands/publish.js @@ -27,8 +27,15 @@ export function hasWrapper(commander: Object, args: Array): boolean { } async function publish(config: Config, pkg: any, flags: Object, dir: string): Promise { + let access = flags.access; + + // if no access level is provided, check package.json for `publishConfig.access` + // see: https://docs.npmjs.com/files/package.json#publishconfig + if (!access && pkg && pkg.publishConfig && pkg.publishConfig.access) { + access = pkg.publishConfig.access; + } + // validate access argument - const access = flags.access; if (access && access !== 'public' && access !== 'restricted') { throw new MessageError(config.reporter.lang('invalidAccess')); } @@ -69,7 +76,7 @@ async function publish(config: Config, pkg: any, flags: Object, dir: string): Pr // create body const root = { _id: pkg.name, - access: flags.access, + access, name: pkg.name, description: pkg.description, 'dist-tags': { From d68b6c96d161ad58833f7751668bfee25a3d4252 Mon Sep 17 00:00:00 2001 From: kaylieEB Date: Tue, 30 Jan 2018 13:09:01 +0100 Subject: [PATCH 34/34] feat(upgrade, add): Separately log added/upgraded dependencies (#5227) * feat(upgrade, add): Separate added/upgraded dependencies into direct/transitive When adding or upgrading dependencies, group the dependencies into directly required ones vs. transitive ones so that version shown is clearer to the end user. https://github.com/yarnpkg/rfcs/blob/master/accepted/0000-show-updated-packages-only.md * fix tests * flow * review feedback * add snapshots * update snapshots --- __tests__/__snapshots__/index.js.snap | 78 +++++++++++++++++++ __tests__/__snapshots__/integration.js.snap | 5 +- __tests__/commands/upgrade.js | 28 +++++++ .../upgrade/direct-dependency/package.json | 5 ++ .../upgrade/direct-dependency/yarn.lock | 13 ++++ __tests__/index.js | 36 +++------ src/cli/commands/add.js | 26 ++++++- src/reporters/lang/en.js | 2 + 8 files changed, 164 insertions(+), 29 deletions(-) create mode 100644 __tests__/__snapshots__/index.js.snap create mode 100644 __tests__/fixtures/upgrade/direct-dependency/package.json create mode 100644 __tests__/fixtures/upgrade/direct-dependency/yarn.lock diff --git a/__tests__/__snapshots__/index.js.snap b/__tests__/__snapshots__/index.js.snap new file mode 100644 index 0000000000..c7154dd81b --- /dev/null +++ b/__tests__/__snapshots__/index.js.snap @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should add lockfile package 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved lockfile.", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ lockfile@1.0.3", + "info All dependencies", + "└─ lockfile@1.0.3", +] +`; + +exports[`should add package 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved lockfile.", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ left-pad@1.2.0", + "info All dependencies", + "└─ left-pad@1.2.0", +] +`; + +exports[`should add package with frozen-lockfile option 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ repeating@3.0.0", + "info All dependencies", + "└─ repeating@3.0.0", +] +`; + +exports[`should add package with no-lockfile option 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ repeating@3.0.0", + "info All dependencies", + "└─ repeating@3.0.0", +] +`; + +exports[`should add package with no-lockfile option in front 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ split-lines@1.1.0", + "info All dependencies", + "└─ split-lines@1.1.0", +] +`; diff --git a/__tests__/__snapshots__/integration.js.snap b/__tests__/__snapshots__/integration.js.snap index 88b894d032..e736395656 100644 --- a/__tests__/__snapshots__/integration.js.snap +++ b/__tests__/__snapshots__/integration.js.snap @@ -8,5 +8,8 @@ exports[`yarnrc-args 1`] = ` {\\"type\\":\\"step\\",\\"data\\":{\\"message\\":\\"Building fresh packages\\",\\"current\\":4,\\"total\\":4}} {\\"type\\":\\"success\\",\\"data\\":\\"Saved lockfile.\\"} {\\"type\\":\\"success\\",\\"data\\":\\"Saved 1 new dependency.\\"} -{\\"type\\":\\"tree\\",\\"data\\":{\\"type\\":\\"newDependencies\\",\\"trees\\":[{\\"name\\":\\"left-pad@1.1.3\\",\\"children\\":[],\\"hint\\":null,\\"color\\":null,\\"depth\\":0}]}}" +{\\"type\\":\\"info\\",\\"data\\":\\"Direct dependencies\\"} +{\\"type\\":\\"tree\\",\\"data\\":{\\"type\\":\\"newDirectDependencies\\",\\"trees\\":[{\\"name\\":\\"left-pad@1.1.3\\",\\"children\\":[],\\"hint\\":null,\\"color\\":null,\\"depth\\":0}]}} +{\\"type\\":\\"info\\",\\"data\\":\\"All dependencies\\"} +{\\"type\\":\\"tree\\",\\"data\\":{\\"type\\":\\"newAllDependencies\\",\\"trees\\":[{\\"name\\":\\"left-pad@1.1.3\\",\\"children\\":[],\\"hint\\":null,\\"color\\":null,\\"depth\\":0}]}}" `; diff --git a/__tests__/commands/upgrade.js b/__tests__/commands/upgrade.js index c70a3272cf..07be7d78be 100644 --- a/__tests__/commands/upgrade.js +++ b/__tests__/commands/upgrade.js @@ -275,6 +275,34 @@ test.concurrent('upgrades optional dependency packages not in registry', (): Pro }); }); +test.concurrent('informs the type of dependency after upgrade', (): Promise => { + return buildRun( + reporters.BufferReporter, + fixturesLoc, + async (args, flags, config, reporter): Promise => { + await upgrade(config, reporter, flags, args); + + const output = reporter.getBuffer(); + const infos = output.filter(({type}) => type === 'info'); + const getTreeInfo = pkgName => + output.filter( + ({type, data: {trees = []}}) => type === 'tree' && trees.some(({name}) => name.indexOf(pkgName) > -1), + ); + + expect( + infos.some(info => { + return info.data.toString().indexOf('Direct dependencies') > -1; + }), + ).toEqual(true); + expect(getTreeInfo('async')).toHaveLength(2); + expect(getTreeInfo('lodash')).toHaveLength(1); + }, + ['async'], + {latest: true}, + 'direct-dependency', + ); +}); + test.concurrent('warns when peer dependency is not met after upgrade', (): Promise => { return buildRun( reporters.BufferReporter, diff --git a/__tests__/fixtures/upgrade/direct-dependency/package.json b/__tests__/fixtures/upgrade/direct-dependency/package.json new file mode 100644 index 0000000000..ace0343538 --- /dev/null +++ b/__tests__/fixtures/upgrade/direct-dependency/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "async": "2.0.0" + } +} diff --git a/__tests__/fixtures/upgrade/direct-dependency/yarn.lock b/__tests__/fixtures/upgrade/direct-dependency/yarn.lock new file mode 100644 index 0000000000..7228efd284 --- /dev/null +++ b/__tests__/fixtures/upgrade/direct-dependency/yarn.lock @@ -0,0 +1,13 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +async@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.0.0.tgz#d0900ad385af13804540a109c42166e3ae7b2b9d" + dependencies: + lodash "^4.8.0" + +lodash@^4.8.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" diff --git a/__tests__/index.js b/__tests__/index.js index 88541afc5b..48b8cec5f1 100644 --- a/__tests__/index.js +++ b/__tests__/index.js @@ -60,20 +60,8 @@ async function execCommand( }); } -function expectAddSuccessfullOutput(stdout, pkg) { - const lastLines = stdout.slice(stdout.length - 4); - expect(lastLines[0]).toEqual('success Saved lockfile.'); - expect(lastLines[1]).toEqual('success Saved 1 new dependency.'); - expect(lastLines[2]).toContain(pkg); - expect(lastLines[3]).toContain('Done'); -} - -function expectAddSuccessfullOutputWithNoLockFile(stdout, pkg) { - const lastLines = stdout.slice(stdout.length - 4); - expect(lastLines[0]).not.toEqual('success Saved lockfile.'); - expect(lastLines[1]).toEqual('success Saved 1 new dependency.'); - expect(lastLines[2]).toContain(pkg); - expect(lastLines[3]).toContain('Done'); +function expectAddOutput(stdout) { + expect(stdout.slice(1, stdout.length - 1)).toMatchSnapshot(); } function expectRunOutput(stdout) { @@ -112,29 +100,29 @@ function expectAnInfoMessageAfterError(command: Promise>, expecte .catch(error => expect(error.stdout).toContain(expectedInfo)); } -test.concurrent('should add package', async () => { +test('should add package', async () => { const stdout = await execCommand('add', ['left-pad'], 'run-add', true); - expectAddSuccessfullOutput(stdout, 'left-pad'); + expectAddOutput(stdout); }); -test.concurrent('should add package with no-lockfile option', async () => { +test('should add package with no-lockfile option', async () => { const stdout = await execCommand('add', ['repeating', '--no-lockfile'], 'run-add-option', true); - expectAddSuccessfullOutputWithNoLockFile(stdout, 'repeating'); + expectAddOutput(stdout); }); -test.concurrent('should add package with frozen-lockfile option', async () => { +test('should add package with frozen-lockfile option', async () => { const stdout = await execCommand('add', ['repeating', '--frozen-lockfile'], 'run-add-option', true); - expectAddSuccessfullOutputWithNoLockFile(stdout, 'repeating'); + expectAddOutput(stdout); }); -test.concurrent('should add package with no-lockfile option in front', async () => { +test('should add package with no-lockfile option in front', async () => { const stdout = await execCommand('add', ['--no-lockfile', 'split-lines'], 'run-add-option-in-front', true); - expectAddSuccessfullOutputWithNoLockFile(stdout, 'split-lines'); + expectAddOutput(stdout); }); -test.concurrent('should add lockfile package', async () => { +test('should add lockfile package', async () => { const stdout = await execCommand('add', ['lockfile'], 'run-add-lockfile', true); - expectAddSuccessfullOutput(stdout, 'lockfile'); + expectAddOutput(stdout); }); // test is failing on Node 4, https://travis-ci.org/yarnpkg/yarn/jobs/216254539 diff --git a/src/cli/commands/add.js b/src/cli/commands/add.js index 5d14bc698c..617c676397 100644 --- a/src/cli/commands/add.js +++ b/src/cli/commands/add.js @@ -204,10 +204,28 @@ export class Add extends Install { const merged = [...patterns, ...this.addedPatterns]; const {trees, count} = await buildTree(this.resolver, this.linker, merged, opts, true, true); - this.reporter.success( - count === 1 ? this.reporter.lang('savedNewDependency') : this.reporter.lang('savedNewDependencies', count), - ); - this.reporter.tree('newDependencies', trees); + + if (count === 1) { + this.reporter.success(this.reporter.lang('savedNewDependency')); + } else { + this.reporter.success(this.reporter.lang('savedNewDependencies', count)); + } + + if (!count) { + return; + } + + const resolverPatterns = new Set(); + for (const pattern of patterns) { + const {version, name} = this.resolver.getResolvedPattern(pattern) || {}; + resolverPatterns.add(`${name}@${version}`); + } + const directRequireDependencies = trees.filter(({name}) => resolverPatterns.has(name)); + + this.reporter.info(this.reporter.lang('directDependencies')); + this.reporter.tree('newDirectDependencies', directRequireDependencies); + this.reporter.info(this.reporter.lang('allDependencies')); + this.reporter.tree('newAllDependencies', trees); } /** diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index dfaa37c0ee..0fc262aa51 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -239,6 +239,8 @@ const messages = { savedNewDependency: 'Saved 1 new dependency.', savedNewDependencies: 'Saved $0 new dependencies.', + directDependencies: 'Direct dependencies', + allDependencies: 'All dependencies', foundWarnings: 'Found $0 warnings.', foundErrors: 'Found $0 errors.',