From 6a838adea836ef38c9d82944ecc12b93e3248473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Tue, 13 Nov 2018 12:26:05 +0000 Subject: [PATCH 1/5] Implements optional peer dependencies --- __tests__/commands/install/integration.js | 16 ++++++++++++++++ .../missing-opt-peer-dep/foo/package.json | 7 +++++++ .../install/missing-opt-peer-dep/package.json | 6 ++++++ .../install/missing-peer-dep/foo/package.json | 7 +++++++ .../install/missing-peer-dep/package.json | 6 ++++++ src/package-linker.js | 6 ++++-- 6 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 __tests__/fixtures/install/missing-opt-peer-dep/foo/package.json create mode 100644 __tests__/fixtures/install/missing-opt-peer-dep/package.json create mode 100644 __tests__/fixtures/install/missing-peer-dep/foo/package.json create mode 100644 __tests__/fixtures/install/missing-peer-dep/package.json diff --git a/__tests__/commands/install/integration.js b/__tests__/commands/install/integration.js index cad6455f0e..116f59c4c4 100644 --- a/__tests__/commands/install/integration.js +++ b/__tests__/commands/install/integration.js @@ -1123,3 +1123,19 @@ test('install will not warn for missing peerDep when both shallower and deeper', const warningMessage = messageParts.every(part => stdout.includes(part)); expect(warningMessage).toBe(false); })); + +test('install will warn for missing peer dependencies', () => + runInstall({}, 'missing-peer-dep', (config, reporter, install, getStdout) => { + const stdout = getStdout(); + const messageParts = reporter.lang('unmetPeer', 'undefined').split('undefined'); + const warningMessage = messageParts.every(part => stdout.includes(part)); + expect(warningMessage).toBe(true); + })); + +test('install will not warn for missing optional peer dependencies', () => + runInstall({}, 'missing-opt-peer-dep', (config, reporter, install, getStdout) => { + const stdout = getStdout(); + const messageParts = reporter.lang('unmetPeer', 'undefined').split('undefined'); + const warningMessage = messageParts.every(part => stdout.includes(part)); + expect(warningMessage).toBe(false); + })); diff --git a/__tests__/fixtures/install/missing-opt-peer-dep/foo/package.json b/__tests__/fixtures/install/missing-opt-peer-dep/foo/package.json new file mode 100644 index 0000000000..8c615a8b8e --- /dev/null +++ b/__tests__/fixtures/install/missing-opt-peer-dep/foo/package.json @@ -0,0 +1,7 @@ +{ + "name": "foo", + "version": "1.0.0", + "peerDependencies": { + "bar": "optional:*" + } +} diff --git a/__tests__/fixtures/install/missing-opt-peer-dep/package.json b/__tests__/fixtures/install/missing-opt-peer-dep/package.json new file mode 100644 index 0000000000..eb09afab80 --- /dev/null +++ b/__tests__/fixtures/install/missing-opt-peer-dep/package.json @@ -0,0 +1,6 @@ +{ + "name": "missing-peer-dep", + "dependencies": { + "foo": "file:./foo" + } +} diff --git a/__tests__/fixtures/install/missing-peer-dep/foo/package.json b/__tests__/fixtures/install/missing-peer-dep/foo/package.json new file mode 100644 index 0000000000..4eff210f8f --- /dev/null +++ b/__tests__/fixtures/install/missing-peer-dep/foo/package.json @@ -0,0 +1,7 @@ +{ + "name": "foo", + "version": "1.0.0", + "peerDependencies": { + "bar": "*" + } +} diff --git a/__tests__/fixtures/install/missing-peer-dep/package.json b/__tests__/fixtures/install/missing-peer-dep/package.json new file mode 100644 index 0000000000..eb09afab80 --- /dev/null +++ b/__tests__/fixtures/install/missing-peer-dep/package.json @@ -0,0 +1,6 @@ +{ + "name": "missing-peer-dep", + "dependencies": { + "foo": "file:./foo" + } +} diff --git a/src/package-linker.js b/src/package-linker.js index 463a9835ce..79020c3e87 100644 --- a/src/package-linker.js +++ b/src/package-linker.js @@ -617,7 +617,9 @@ export default class PackageLinker { }; for (const peerDepName in peerDeps) { - const range = peerDeps[peerDepName]; + const range = peerDeps[peerDepName].replace(/^optional:/, ''); + const isOptional = peerDeps[peerDepName].startsWith('optional:'); + const peerPkgs = this.resolver.getAllInfoForPackageName(peerDepName); let peerError = 'unmetPeer'; @@ -649,7 +651,7 @@ export default class PackageLinker { resolvedPeerPkg.level, ), ); - } else { + } else if (!isOptional) { this.reporter.warn( this.reporter.lang( peerError, From 27d6b1a29f3ec29817330e2ea83ada47fc660b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Tue, 20 Nov 2018 15:19:22 +0000 Subject: [PATCH 2/5] Implements the new peerDependenciesMeta field --- .../missing-opt-peer-dep/foo/package.json | 7 ++++++- src/package-linker.js | 10 ++++++++-- src/types.js | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/__tests__/fixtures/install/missing-opt-peer-dep/foo/package.json b/__tests__/fixtures/install/missing-opt-peer-dep/foo/package.json index 8c615a8b8e..5ef4d306d0 100644 --- a/__tests__/fixtures/install/missing-opt-peer-dep/foo/package.json +++ b/__tests__/fixtures/install/missing-opt-peer-dep/foo/package.json @@ -2,6 +2,11 @@ "name": "foo", "version": "1.0.0", "peerDependencies": { - "bar": "optional:*" + "bar": "*" + }, + "peerDependenciesMeta": { + "bar": { + "optional": true + } } } diff --git a/src/package-linker.js b/src/package-linker.js index 79020c3e87..7680f5cfd4 100644 --- a/src/package-linker.js +++ b/src/package-linker.js @@ -595,11 +595,15 @@ export default class PackageLinker { resolvePeerModules() { for (const pkg of this.resolver.getManifests()) { const peerDeps = pkg.peerDependencies; + const peerDepsMeta = pkg.peerDependenciesMeta; + if (!peerDeps) { continue; } + const ref = pkg._reference; invariant(ref, 'Package reference is missing'); + // TODO: We are taking the "shortest" ref tree but there may be multiple ref trees with the same length const refTree = ref.requests.map(req => req.parentNames).sort((arr1, arr2) => arr1.length - arr2.length)[0]; @@ -617,8 +621,10 @@ export default class PackageLinker { }; for (const peerDepName in peerDeps) { - const range = peerDeps[peerDepName].replace(/^optional:/, ''); - const isOptional = peerDeps[peerDepName].startsWith('optional:'); + const range = peerDeps[peerDepName]; + const meta = peerDepsMeta && peerDepsMeta[peerDepName]; + + const isOptional = meta && meta.optional ? true : false; const peerPkgs = this.resolver.getAllInfoForPackageName(peerDepName); diff --git a/src/types.js b/src/types.js index 092e9b20cd..d68bb262e7 100644 --- a/src/types.js +++ b/src/types.js @@ -13,6 +13,21 @@ export type CLIFunction = (config: Config, reporter: Reporter, flags: Object, ar type _CLIFunctionReturn = boolean; export type CLIFunctionReturn = ?_CLIFunctionReturn | Promise; +export type DependencyMeta = { +}; + +export type DependenciesMeta = { + [name: string]: DependencyMeta, +}; + +export type PeerDependencyMeta = { + optional?: boolean, +}; + +export type PeerDependenciesMeta = { + [name: string]: DependencyMeta, +}; + // dependency request pattern data structure that's used to request dependencies from a // PackageResolver export type DependencyRequestPattern = { @@ -132,6 +147,9 @@ export type Manifest = { peerDependencies?: Dependencies, optionalDependencies?: Dependencies, + dependenciesMeta?: DependenciesMeta, + peerDependenciesMeta?: PeerDependenciesMeta, + bundleDependencies?: Array, bundledDependencies?: Array, From cc4fd17f793cb8c97aba4114fafa1b7b46ed9a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Tue, 20 Nov 2018 15:27:52 +0000 Subject: [PATCH 3/5] Runs prettier --- src/package-linker.js | 2 +- src/types.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/package-linker.js b/src/package-linker.js index 7680f5cfd4..66308d2221 100644 --- a/src/package-linker.js +++ b/src/package-linker.js @@ -624,7 +624,7 @@ export default class PackageLinker { const range = peerDeps[peerDepName]; const meta = peerDepsMeta && peerDepsMeta[peerDepName]; - const isOptional = meta && meta.optional ? true : false; + const isOptional = !!(meta && meta.optional); const peerPkgs = this.resolver.getAllInfoForPackageName(peerDepName); diff --git a/src/types.js b/src/types.js index d68bb262e7..934c3defda 100644 --- a/src/types.js +++ b/src/types.js @@ -13,8 +13,7 @@ export type CLIFunction = (config: Config, reporter: Reporter, flags: Object, ar type _CLIFunctionReturn = boolean; export type CLIFunctionReturn = ?_CLIFunctionReturn | Promise; -export type DependencyMeta = { -}; +export type DependencyMeta = {}; export type DependenciesMeta = { [name: string]: DependencyMeta, From 684a2f047df4d67f0f7a42741a626464b6522d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Tue, 20 Nov 2018 15:31:13 +0000 Subject: [PATCH 4/5] Updates the changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88442452d4..982a3f560e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa ## Master +- Implements a new `package.json` field: `peerDependenciesMeta` + + [#6671](https://github.com/yarnpkg/yarn/pull/6671) - [**Maël Nison**](https://twitter.com/arcanis) + +- Adds an `optional` settings to `peerDependenciesMeta` to silence missing peer dependency warnings + + [#6671](https://github.com/yarnpkg/yarn/pull/6671) - [**Maël Nison**](https://twitter.com/arcanis) + - Fixes a resolution issue when a package had an invalid `main` entry [#6682](https://github.com/yarnpkg/yarn/pull/6682) - [**Maël Nison**](https://twitter.com/arcanis) From abbd9b2bd38f6aaca108148632e909ad037c16fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Tue, 20 Nov 2018 16:00:26 +0000 Subject: [PATCH 5/5] Fixes flow --- src/types.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.js b/src/types.js index 934c3defda..442b54ff7d 100644 --- a/src/types.js +++ b/src/types.js @@ -24,7 +24,7 @@ export type PeerDependencyMeta = { }; export type PeerDependenciesMeta = { - [name: string]: DependencyMeta, + [name: string]: PeerDependencyMeta, }; // dependency request pattern data structure that's used to request dependencies from a