@yarnpkg/plugin-essentials 4.1.2 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -4,9 +4,12 @@ import { Writable } from 'stream';
|
|
|
4
4
|
export default class ExplainPeerRequirementsCommand extends BaseCommand {
|
|
5
5
|
static paths: string[][];
|
|
6
6
|
static usage: import("clipanion").Usage;
|
|
7
|
-
hash: string;
|
|
7
|
+
hash: string | undefined;
|
|
8
8
|
execute(): Promise<0 | 1>;
|
|
9
9
|
}
|
|
10
|
-
export declare function
|
|
10
|
+
export declare function explainPeerRequirement(peerRequirementsHash: string, project: Project, opts: {
|
|
11
|
+
stdout: Writable;
|
|
12
|
+
}): Promise<0 | 1>;
|
|
13
|
+
export declare function explainPeerRequirements(project: Project, opts: {
|
|
11
14
|
stdout: Writable;
|
|
12
15
|
}): Promise<0 | 1>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.explainPeerRequirement = explainPeerRequirement;
|
|
3
4
|
exports.explainPeerRequirements = explainPeerRequirements;
|
|
4
5
|
const tslib_1 = require("tslib");
|
|
5
6
|
const cli_1 = require("@yarnpkg/cli");
|
|
@@ -11,6 +12,7 @@ class ExplainPeerRequirementsCommand extends cli_1.BaseCommand {
|
|
|
11
12
|
constructor() {
|
|
12
13
|
super(...arguments);
|
|
13
14
|
this.hash = clipanion_1.Option.String({
|
|
15
|
+
required: false,
|
|
14
16
|
validator: t.cascade(t.isString(), [
|
|
15
17
|
t.matchesRegExp(/^p[0-9a-f]{5}$/),
|
|
16
18
|
]),
|
|
@@ -23,9 +25,16 @@ class ExplainPeerRequirementsCommand extends cli_1.BaseCommand {
|
|
|
23
25
|
restoreResolutions: false,
|
|
24
26
|
});
|
|
25
27
|
await project.applyLightResolution();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if (typeof this.hash !== `undefined`) {
|
|
29
|
+
return await explainPeerRequirement(this.hash, project, {
|
|
30
|
+
stdout: this.context.stdout,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return await explainPeerRequirements(project, {
|
|
35
|
+
stdout: this.context.stdout,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
29
38
|
}
|
|
30
39
|
}
|
|
31
40
|
ExplainPeerRequirementsCommand.paths = [
|
|
@@ -34,29 +43,51 @@ ExplainPeerRequirementsCommand.paths = [
|
|
|
34
43
|
ExplainPeerRequirementsCommand.usage = clipanion_1.Command.Usage({
|
|
35
44
|
description: `explain a set of peer requirements`,
|
|
36
45
|
details: `
|
|
37
|
-
A
|
|
46
|
+
A peer requirement represents all peer requests that a subject must satisfy when providing a requested package to requesters.
|
|
38
47
|
|
|
39
|
-
When the hash argument is specified, this command prints a detailed explanation of
|
|
48
|
+
When the hash argument is specified, this command prints a detailed explanation of the peer requirement corresponding to the hash and whether it is satisfied or not.
|
|
40
49
|
|
|
41
|
-
When used without arguments, this command lists all
|
|
50
|
+
When used without arguments, this command lists all peer requirements and the corresponding hash that can be used to get detailed information about a given requirement.
|
|
42
51
|
|
|
43
52
|
**Note:** A hash is a six-letter p-prefixed code that can be obtained from peer dependency warnings or from the list of all peer requirements (\`yarn explain peer-requirements\`).
|
|
44
53
|
`,
|
|
45
54
|
examples: [[
|
|
46
|
-
`Explain the corresponding
|
|
55
|
+
`Explain the corresponding peer requirement for a hash`,
|
|
47
56
|
`$0 explain peer-requirements p1a4ed`,
|
|
48
57
|
], [
|
|
49
|
-
`List all
|
|
58
|
+
`List all peer requirements`,
|
|
50
59
|
`$0 explain peer-requirements`,
|
|
51
60
|
]],
|
|
52
61
|
});
|
|
53
62
|
exports.default = ExplainPeerRequirementsCommand;
|
|
54
|
-
async function
|
|
63
|
+
async function explainPeerRequirement(peerRequirementsHash, project, opts) {
|
|
64
|
+
const root = project.peerRequirementNodes.get(peerRequirementsHash);
|
|
65
|
+
if (typeof root === `undefined`)
|
|
66
|
+
throw new Error(`No peerDependency requirements found for hash: "${peerRequirementsHash}"`);
|
|
67
|
+
const seen = new Set();
|
|
68
|
+
const makeTreeNode = (request) => {
|
|
69
|
+
if (seen.has(request.requester.locatorHash)) {
|
|
70
|
+
return {
|
|
71
|
+
value: core_1.formatUtils.tuple(core_1.formatUtils.Type.DEPENDENT, { locator: request.requester, descriptor: request.descriptor }),
|
|
72
|
+
children: request.children.size > 0
|
|
73
|
+
? [{ value: core_1.formatUtils.tuple(core_1.formatUtils.Type.NO_HINT, `...`) }]
|
|
74
|
+
: [],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
seen.add(request.requester.locatorHash);
|
|
78
|
+
return {
|
|
79
|
+
value: core_1.formatUtils.tuple(core_1.formatUtils.Type.DEPENDENT, { locator: request.requester, descriptor: request.descriptor }),
|
|
80
|
+
children: Object.fromEntries(Array.from(request.children.values(), child => {
|
|
81
|
+
return [
|
|
82
|
+
core_1.structUtils.stringifyLocator(child.requester),
|
|
83
|
+
makeTreeNode(child),
|
|
84
|
+
];
|
|
85
|
+
})),
|
|
86
|
+
};
|
|
87
|
+
};
|
|
55
88
|
const warning = project.peerWarnings.find(warning => {
|
|
56
89
|
return warning.hash === peerRequirementsHash;
|
|
57
90
|
});
|
|
58
|
-
if (typeof warning === `undefined`)
|
|
59
|
-
throw new Error(`No peerDependency requirements found for hash: "${peerRequirementsHash}"`);
|
|
60
91
|
const report = await core_1.StreamReport.start({
|
|
61
92
|
configuration: project.configuration,
|
|
62
93
|
stdout: opts.stdout,
|
|
@@ -64,71 +95,97 @@ async function explainPeerRequirements(peerRequirementsHash, project, opts) {
|
|
|
64
95
|
includePrefix: false,
|
|
65
96
|
}, async (report) => {
|
|
66
97
|
const Marks = core_1.formatUtils.mark(project.configuration);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
98
|
+
const mark = warning ? Marks.Cross : Marks.Check;
|
|
99
|
+
report.reportInfo(core_1.MessageName.UNNAMED, `Package ${core_1.formatUtils.pretty(project.configuration, root.subject, core_1.formatUtils.Type.LOCATOR)} is requested to provide ${core_1.formatUtils.pretty(project.configuration, root.ident, core_1.formatUtils.Type.IDENT)} by its descendants`);
|
|
100
|
+
report.reportSeparator();
|
|
101
|
+
report.reportInfo(core_1.MessageName.UNNAMED, core_1.formatUtils.pretty(project.configuration, root.subject, core_1.formatUtils.Type.LOCATOR));
|
|
102
|
+
core_1.treeUtils.emitTree({
|
|
103
|
+
children: Object.fromEntries(Array.from(root.requests.values(), request => {
|
|
104
|
+
return [
|
|
105
|
+
core_1.structUtils.stringifyLocator(request.requester),
|
|
106
|
+
makeTreeNode(request),
|
|
107
|
+
];
|
|
108
|
+
})),
|
|
109
|
+
}, {
|
|
110
|
+
configuration: project.configuration,
|
|
111
|
+
stdout: opts.stdout,
|
|
112
|
+
json: false,
|
|
113
|
+
});
|
|
114
|
+
report.reportSeparator();
|
|
115
|
+
if (root.provided.range === `missing:`) {
|
|
116
|
+
const problem = warning ? `` : ` , but all peer requests are optional`;
|
|
117
|
+
report.reportInfo(core_1.MessageName.UNNAMED, `${mark} Package ${core_1.formatUtils.pretty(project.configuration, root.subject, core_1.formatUtils.Type.LOCATOR)} does not provide ${core_1.formatUtils.pretty(project.configuration, root.ident, core_1.formatUtils.Type.IDENT)}${problem}.`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const providedLocatorHash = project.storedResolutions.get(root.provided.descriptorHash);
|
|
121
|
+
if (!providedLocatorHash)
|
|
122
|
+
throw new Error(`Assertion failed: Expected the descriptor to be registered`);
|
|
123
|
+
const providedPackage = project.storedPackages.get(providedLocatorHash);
|
|
124
|
+
if (!providedPackage)
|
|
125
|
+
throw new Error(`Assertion failed: Expected the package to be registered`);
|
|
126
|
+
report.reportInfo(core_1.MessageName.UNNAMED, `${mark} Package ${core_1.formatUtils.pretty(project.configuration, root.subject, core_1.formatUtils.Type.LOCATOR)} provides ${core_1.formatUtils.pretty(project.configuration, root.ident, core_1.formatUtils.Type.IDENT)} with version ${core_1.structUtils.prettyReference(project.configuration, providedPackage.version ?? `0.0.0`)}, ${warning ? `which does not satisfy all requests.` : `which satisfies all requests`}`);
|
|
127
|
+
if (warning?.type === core_1.PeerWarningType.NodeNotCompatible) {
|
|
128
|
+
if (warning.range) {
|
|
129
|
+
report.reportInfo(core_1.MessageName.UNNAMED, ` The combined requested range is ${core_1.formatUtils.pretty(project.configuration, warning.range, core_1.formatUtils.Type.RANGE)}`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
report.reportInfo(core_1.MessageName.UNNAMED, ` Unfortunately, the requested ranges have no overlap`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
return report.exitCode();
|
|
138
|
+
}
|
|
139
|
+
async function explainPeerRequirements(project, opts) {
|
|
140
|
+
const report = await core_1.StreamReport.start({
|
|
141
|
+
configuration: project.configuration,
|
|
142
|
+
stdout: opts.stdout,
|
|
143
|
+
includeFooter: false,
|
|
144
|
+
includePrefix: false,
|
|
145
|
+
}, async (report) => {
|
|
146
|
+
const Marks = core_1.formatUtils.mark(project.configuration);
|
|
147
|
+
const sorted = core_1.miscUtils.sortMap(project.peerRequirementNodes, [
|
|
148
|
+
([, requirement]) => core_1.structUtils.stringifyLocator(requirement.subject),
|
|
149
|
+
([, requirement]) => core_1.structUtils.stringifyIdent(requirement.ident),
|
|
150
|
+
]);
|
|
151
|
+
for (const [, peerRequirement] of sorted.values()) {
|
|
152
|
+
if (!peerRequirement.root)
|
|
153
|
+
continue;
|
|
154
|
+
const warning = project.peerWarnings.find(warning => {
|
|
155
|
+
return warning.hash === peerRequirement.hash;
|
|
156
|
+
});
|
|
157
|
+
const allRequests = [...core_1.structUtils.allPeerRequests(peerRequirement)];
|
|
158
|
+
let andOthers;
|
|
159
|
+
if (allRequests.length > 2)
|
|
160
|
+
andOthers = ` and ${allRequests.length - 1} other dependencies`;
|
|
161
|
+
else if (allRequests.length === 2)
|
|
162
|
+
andOthers = ` and 1 other dependency`;
|
|
163
|
+
else
|
|
164
|
+
andOthers = ``;
|
|
165
|
+
if (peerRequirement.provided.range !== `missing:`) {
|
|
166
|
+
const providedResolution = project.storedResolutions.get(peerRequirement.provided.descriptorHash);
|
|
167
|
+
if (!providedResolution)
|
|
168
|
+
throw new Error(`Assertion failed: Expected the resolution to have been registered`);
|
|
169
|
+
const providedPkg = project.storedPackages.get(providedResolution);
|
|
170
|
+
if (!providedPkg)
|
|
171
|
+
throw new Error(`Assertion failed: Expected the provided package to have been registered`);
|
|
172
|
+
const message = `${core_1.formatUtils.pretty(project.configuration, peerRequirement.hash, core_1.formatUtils.Type.CODE)} → ${warning ? Marks.Cross : Marks.Check} ${core_1.structUtils.prettyLocator(project.configuration, peerRequirement.subject)} provides ${core_1.structUtils.prettyLocator(project.configuration, providedPkg)} to ${core_1.structUtils.prettyLocator(project.configuration, allRequests[0].requester)}${andOthers}`;
|
|
173
|
+
if (warning) {
|
|
174
|
+
report.reportWarning(core_1.MessageName.UNNAMED, message);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
report.reportInfo(core_1.MessageName.UNNAMED, message);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
const message = `${core_1.formatUtils.pretty(project.configuration, peerRequirement.hash, core_1.formatUtils.Type.CODE)} → ${warning ? Marks.Cross : Marks.Check} ${core_1.structUtils.prettyLocator(project.configuration, peerRequirement.subject)} doesn't provide ${core_1.structUtils.prettyIdent(project.configuration, peerRequirement.ident)} to ${core_1.structUtils.prettyLocator(project.configuration, allRequests[0].requester)}${andOthers}`;
|
|
182
|
+
if (warning) {
|
|
183
|
+
report.reportWarning(core_1.MessageName.UNNAMED, message);
|
|
125
184
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
{
|
|
129
|
-
report.reportInfo(core_1.MessageName.UNNAMED, `The ${core_1.formatUtils.pretty(project.configuration, `yarn explain peer-requirements`, core_1.formatUtils.Type.CODE)} command doesn't support this warning type yet.`);
|
|
185
|
+
else {
|
|
186
|
+
report.reportInfo(core_1.MessageName.UNNAMED, message);
|
|
130
187
|
}
|
|
131
|
-
|
|
188
|
+
}
|
|
132
189
|
}
|
|
133
190
|
});
|
|
134
191
|
return report.exitCode();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yarnpkg/plugin-essentials",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"license": "BSD-2-Clause",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -20,16 +20,16 @@
|
|
|
20
20
|
"typanion": "^3.14.0"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@yarnpkg/cli": "^4.
|
|
24
|
-
"@yarnpkg/core": "^4.0
|
|
23
|
+
"@yarnpkg/cli": "^4.3.0",
|
|
24
|
+
"@yarnpkg/core": "^4.1.0",
|
|
25
25
|
"@yarnpkg/plugin-git": "^3.0.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/lodash": "^4.14.136",
|
|
29
29
|
"@types/micromatch": "^4.0.1",
|
|
30
30
|
"@types/semver": "^7.1.0",
|
|
31
|
-
"@yarnpkg/cli": "^4.
|
|
32
|
-
"@yarnpkg/core": "^4.0
|
|
31
|
+
"@yarnpkg/cli": "^4.3.0",
|
|
32
|
+
"@yarnpkg/core": "^4.1.0",
|
|
33
33
|
"@yarnpkg/plugin-git": "^3.0.0"
|
|
34
34
|
},
|
|
35
35
|
"repository": {
|