@yarnpkg/plugin-pnpm 1.0.2-rc.1 → 1.1.0-rc.4
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.
- package/lib/PnpmLinker.d.ts +6 -4
- package/lib/PnpmLinker.js +72 -20
- package/package.json +7 -7
package/lib/PnpmLinker.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Descriptor, FetchResult, Installer, InstallPackageExtraApi, Linker, LinkOptions, Locator, MinimalLinkOptions, Package } from '@yarnpkg/core';
|
|
1
|
+
import { Descriptor, FetchResult, Installer, InstallPackageExtraApi, Linker, LinkOptions, Locator, LocatorHash, MinimalLinkOptions, Package } from '@yarnpkg/core';
|
|
2
2
|
import { PortablePath } from '@yarnpkg/fslib';
|
|
3
3
|
export declare type PnpmCustomData = {
|
|
4
|
-
|
|
4
|
+
pathByLocator: Map<LocatorHash, PortablePath>;
|
|
5
|
+
locatorByPath: Map<PortablePath, string>;
|
|
5
6
|
};
|
|
6
7
|
export declare class PnpmLinker implements Linker {
|
|
7
8
|
supportsPackage(pkg: Package, opts: MinimalLinkOptions): boolean;
|
|
@@ -12,7 +13,6 @@ export declare class PnpmLinker implements Linker {
|
|
|
12
13
|
declare class PnpmInstaller implements Installer {
|
|
13
14
|
private opts;
|
|
14
15
|
private asyncActions;
|
|
15
|
-
private packageLocations;
|
|
16
16
|
constructor(opts: LinkOptions);
|
|
17
17
|
getCustomDataKey(): string;
|
|
18
18
|
private customData;
|
|
@@ -34,6 +34,8 @@ declare class PnpmInstaller implements Installer {
|
|
|
34
34
|
}>;
|
|
35
35
|
attachInternalDependencies(locator: Locator, dependencies: Array<[Descriptor, Locator]>): Promise<void>;
|
|
36
36
|
attachExternalDependents(locator: Locator, dependentPaths: Array<PortablePath>): Promise<void>;
|
|
37
|
-
finalizeInstall(): Promise<
|
|
37
|
+
finalizeInstall(): Promise<{
|
|
38
|
+
customData: PnpmCustomData;
|
|
39
|
+
}>;
|
|
38
40
|
}
|
|
39
41
|
export {};
|
package/lib/PnpmLinker.js
CHANGED
|
@@ -12,8 +12,14 @@ class PnpmLinker {
|
|
|
12
12
|
return opts.project.configuration.get(`nodeLinker`) === `pnpm`;
|
|
13
13
|
}
|
|
14
14
|
async findPackageLocation(locator, opts) {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const customDataKey = getCustomDataKey();
|
|
16
|
+
const customData = opts.project.installersCustomData.get(customDataKey);
|
|
17
|
+
if (!customData)
|
|
18
|
+
throw new clipanion_1.UsageError(`The project in ${core_1.formatUtils.pretty(opts.project.configuration, `${opts.project.cwd}/package.json`, core_1.formatUtils.Type.PATH)} doesn't seem to have been installed - running an install there might help`);
|
|
19
|
+
const packageLocation = customData.pathByLocator.get(locator.locatorHash);
|
|
20
|
+
if (typeof packageLocation === `undefined`)
|
|
21
|
+
throw new clipanion_1.UsageError(`Couldn't find ${core_1.structUtils.prettyLocator(opts.project.configuration, locator)} in the currently installed pnpm map - running an install might help`);
|
|
22
|
+
return packageLocation;
|
|
17
23
|
}
|
|
18
24
|
async findPackageLocator(location, opts) {
|
|
19
25
|
const customDataKey = getCustomDataKey();
|
|
@@ -48,8 +54,8 @@ class PnpmInstaller {
|
|
|
48
54
|
constructor(opts) {
|
|
49
55
|
this.opts = opts;
|
|
50
56
|
this.asyncActions = new AsyncActions();
|
|
51
|
-
this.packageLocations = new Map();
|
|
52
57
|
this.customData = {
|
|
58
|
+
pathByLocator: new Map(),
|
|
53
59
|
locatorByPath: new Map(),
|
|
54
60
|
};
|
|
55
61
|
// Nothing to do
|
|
@@ -58,7 +64,8 @@ class PnpmInstaller {
|
|
|
58
64
|
return getCustomDataKey();
|
|
59
65
|
}
|
|
60
66
|
attachCustomData(customData) {
|
|
61
|
-
|
|
67
|
+
// We don't want to attach the data because it's only used in the Linker and we'll recompute it anyways in the Installer,
|
|
68
|
+
// it needs to be invalidated because otherwise we'll never prune the store or we might run into various issues.
|
|
62
69
|
}
|
|
63
70
|
async installPackage(pkg, fetchResult, api) {
|
|
64
71
|
switch (pkg.linkType) {
|
|
@@ -69,7 +76,7 @@ class PnpmInstaller {
|
|
|
69
76
|
}
|
|
70
77
|
async installPackageSoft(pkg, fetchResult, api) {
|
|
71
78
|
const pkgPath = fslib_1.ppath.resolve(fetchResult.packageFs.getRealPath(), fetchResult.prefixPath);
|
|
72
|
-
this.
|
|
79
|
+
this.customData.pathByLocator.set(pkg.locatorHash, pkgPath);
|
|
73
80
|
return {
|
|
74
81
|
packageLocation: pkgPath,
|
|
75
82
|
buildDirective: null,
|
|
@@ -79,7 +86,7 @@ class PnpmInstaller {
|
|
|
79
86
|
var _a;
|
|
80
87
|
const pkgPath = getPackageLocation(pkg, { project: this.opts.project });
|
|
81
88
|
this.customData.locatorByPath.set(pkgPath, core_1.structUtils.stringifyLocator(pkg));
|
|
82
|
-
this.
|
|
89
|
+
this.customData.pathByLocator.set(pkg.locatorHash, pkgPath);
|
|
83
90
|
api.holdFetchResult(this.asyncActions.set(pkg.locatorHash, async () => {
|
|
84
91
|
await fslib_1.xfs.mkdirPromise(pkgPath, { recursive: true });
|
|
85
92
|
// Copy the package source into the <root>/n_m/.store/<hash> directory, so
|
|
@@ -113,17 +120,15 @@ class PnpmInstaller {
|
|
|
113
120
|
this.asyncActions.reduce(locator.locatorHash, async (action) => {
|
|
114
121
|
// Wait that the package is properly installed before starting to copy things into it
|
|
115
122
|
await action;
|
|
116
|
-
const pkgPath = this.
|
|
123
|
+
const pkgPath = this.customData.pathByLocator.get(locator.locatorHash);
|
|
117
124
|
if (typeof pkgPath === `undefined`)
|
|
118
125
|
throw new Error(`Assertion failed: Expected the package to have been registered (${core_1.structUtils.stringifyLocator(locator)})`);
|
|
119
126
|
const nmPath = fslib_1.ppath.join(pkgPath, fslib_1.Filename.nodeModules);
|
|
120
|
-
|
|
121
|
-
await fslib_1.xfs.mkdirpPromise(nmPath);
|
|
127
|
+
const concurrentPromises = [];
|
|
122
128
|
// Retrieve what's currently inside the package's true nm folder. We
|
|
123
129
|
// will use that to figure out what are the extraneous entries we'll
|
|
124
130
|
// need to remove.
|
|
125
131
|
const extraneous = await getNodeModulesListing(nmPath);
|
|
126
|
-
const concurrentPromises = [];
|
|
127
132
|
for (const [descriptor, dependency] of dependencies) {
|
|
128
133
|
// Downgrade virtual workspaces (cf isPnpmVirtualCompatible's documentation)
|
|
129
134
|
let targetDependency = dependency;
|
|
@@ -131,7 +136,7 @@ class PnpmInstaller {
|
|
|
131
136
|
this.opts.report.reportWarning(core_1.MessageName.UNNAMED, `The pnpm linker doesn't support providing different versions to workspaces' peer dependencies`);
|
|
132
137
|
targetDependency = core_1.structUtils.devirtualizeLocator(dependency);
|
|
133
138
|
}
|
|
134
|
-
const depSrcPath = this.
|
|
139
|
+
const depSrcPath = this.customData.pathByLocator.get(targetDependency.locatorHash);
|
|
135
140
|
if (typeof depSrcPath === `undefined`)
|
|
136
141
|
throw new Error(`Assertion failed: Expected the package to have been registered (${core_1.structUtils.stringifyLocator(dependency)})`);
|
|
137
142
|
const name = core_1.structUtils.stringifyIdent(descriptor);
|
|
@@ -158,8 +163,7 @@ class PnpmInstaller {
|
|
|
158
163
|
}
|
|
159
164
|
}));
|
|
160
165
|
}
|
|
161
|
-
|
|
162
|
-
concurrentPromises.push(fslib_1.xfs.removePromise(fslib_1.ppath.join(nmPath, name)));
|
|
166
|
+
concurrentPromises.push(cleanNodeModules(nmPath, extraneous));
|
|
163
167
|
await Promise.all(concurrentPromises);
|
|
164
168
|
});
|
|
165
169
|
}
|
|
@@ -172,9 +176,35 @@ class PnpmInstaller {
|
|
|
172
176
|
await fslib_1.xfs.removePromise(storeLocation);
|
|
173
177
|
}
|
|
174
178
|
else {
|
|
179
|
+
const removals = [];
|
|
175
180
|
const expectedEntries = new Set();
|
|
176
|
-
for (const packageLocation of this.
|
|
177
|
-
|
|
181
|
+
for (const packageLocation of this.customData.pathByLocator.values()) {
|
|
182
|
+
const subpath = fslib_1.ppath.contains(storeLocation, packageLocation);
|
|
183
|
+
if (subpath !== null) {
|
|
184
|
+
const [storeEntry, /* Filename.nodeModules */ , ...identComponents] = subpath.split(fslib_1.ppath.sep);
|
|
185
|
+
expectedEntries.add(storeEntry);
|
|
186
|
+
const storeEntryPath = fslib_1.ppath.join(storeLocation, storeEntry);
|
|
187
|
+
removals.push(fslib_1.xfs.readdirPromise(storeEntryPath)
|
|
188
|
+
.then(entries => {
|
|
189
|
+
return Promise.all(entries.map(async (entry) => {
|
|
190
|
+
const p = fslib_1.ppath.join(storeEntryPath, entry);
|
|
191
|
+
if (entry === fslib_1.Filename.nodeModules) {
|
|
192
|
+
const extraneous = await getNodeModulesListing(p);
|
|
193
|
+
extraneous.delete(identComponents.join(fslib_1.ppath.sep));
|
|
194
|
+
return cleanNodeModules(p, extraneous);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
return fslib_1.xfs.removePromise(p);
|
|
198
|
+
}
|
|
199
|
+
}));
|
|
200
|
+
})
|
|
201
|
+
.catch(error => {
|
|
202
|
+
if (error.code !== `ENOENT`) {
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
}));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
178
208
|
let storeRecords;
|
|
179
209
|
try {
|
|
180
210
|
storeRecords = await fslib_1.xfs.readdirPromise(storeLocation);
|
|
@@ -182,7 +212,6 @@ class PnpmInstaller {
|
|
|
182
212
|
catch {
|
|
183
213
|
storeRecords = [];
|
|
184
214
|
}
|
|
185
|
-
const removals = [];
|
|
186
215
|
for (const record of storeRecords)
|
|
187
216
|
if (!expectedEntries.has(record))
|
|
188
217
|
removals.push(fslib_1.xfs.removePromise(fslib_1.ppath.join(storeLocation, record)));
|
|
@@ -192,12 +221,15 @@ class PnpmInstaller {
|
|
|
192
221
|
// Wait for the package installs to catch up
|
|
193
222
|
await this.asyncActions.wait(),
|
|
194
223
|
await removeIfEmpty(getNodeModulesLocation(this.opts.project));
|
|
224
|
+
return {
|
|
225
|
+
customData: this.customData,
|
|
226
|
+
};
|
|
195
227
|
}
|
|
196
228
|
}
|
|
197
229
|
function getCustomDataKey() {
|
|
198
230
|
return JSON.stringify({
|
|
199
231
|
name: `PnpmInstaller`,
|
|
200
|
-
version:
|
|
232
|
+
version: 2,
|
|
201
233
|
});
|
|
202
234
|
}
|
|
203
235
|
function getNodeModulesLocation(project) {
|
|
@@ -208,7 +240,8 @@ function getStoreLocation(project) {
|
|
|
208
240
|
}
|
|
209
241
|
function getPackageLocation(locator, { project }) {
|
|
210
242
|
const pkgKey = core_1.structUtils.slugifyLocator(locator);
|
|
211
|
-
const
|
|
243
|
+
const prefixPath = core_1.structUtils.getIdentVendorPath(locator);
|
|
244
|
+
const pkgPath = fslib_1.ppath.join(getStoreLocation(project), pkgKey, prefixPath);
|
|
212
245
|
return pkgPath;
|
|
213
246
|
}
|
|
214
247
|
function isPnpmVirtualCompatible(locator, { project }) {
|
|
@@ -241,8 +274,14 @@ async function getNodeModulesListing(nmPath) {
|
|
|
241
274
|
if (entry.name.startsWith(`.`))
|
|
242
275
|
continue;
|
|
243
276
|
if (entry.name.startsWith(`@`)) {
|
|
244
|
-
|
|
245
|
-
|
|
277
|
+
const scopeListing = await fslib_1.xfs.readdirPromise(fslib_1.ppath.join(nmPath, entry.name), { withFileTypes: true });
|
|
278
|
+
if (scopeListing.length === 0) {
|
|
279
|
+
listing.set(entry.name, entry);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
for (const subEntry of scopeListing) {
|
|
283
|
+
listing.set(`${entry.name}/${subEntry.name}`, subEntry);
|
|
284
|
+
}
|
|
246
285
|
}
|
|
247
286
|
}
|
|
248
287
|
else {
|
|
@@ -257,6 +296,19 @@ async function getNodeModulesListing(nmPath) {
|
|
|
257
296
|
}
|
|
258
297
|
return listing;
|
|
259
298
|
}
|
|
299
|
+
async function cleanNodeModules(nmPath, extraneous) {
|
|
300
|
+
var _a;
|
|
301
|
+
const removeNamePromises = [];
|
|
302
|
+
const scopesToRemove = new Set();
|
|
303
|
+
for (const name of extraneous.keys()) {
|
|
304
|
+
removeNamePromises.push(fslib_1.xfs.removePromise(fslib_1.ppath.join(nmPath, name)));
|
|
305
|
+
const scope = (_a = core_1.structUtils.tryParseIdent(name)) === null || _a === void 0 ? void 0 : _a.scope;
|
|
306
|
+
if (scope) {
|
|
307
|
+
scopesToRemove.add(`@${scope}`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return Promise.all(removeNamePromises).then(() => Promise.all([...scopesToRemove].map(scope => removeIfEmpty(fslib_1.ppath.join(nmPath, scope)))));
|
|
311
|
+
}
|
|
260
312
|
async function removeIfEmpty(dir) {
|
|
261
313
|
try {
|
|
262
314
|
await fslib_1.xfs.rmdirPromise(dir);
|
package/package.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yarnpkg/plugin-pnpm",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0-rc.4",
|
|
4
4
|
"license": "BSD-2-Clause",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@yarnpkg/fslib": "^2.6.
|
|
8
|
-
"@yarnpkg/plugin-pnp": "^3.1.2-rc.
|
|
7
|
+
"@yarnpkg/fslib": "^2.6.1-rc.1",
|
|
8
|
+
"@yarnpkg/plugin-pnp": "^3.1.2-rc.6",
|
|
9
9
|
"@yarnpkg/plugin-stage": "^3.1.1",
|
|
10
10
|
"clipanion": "^3.0.1",
|
|
11
11
|
"p-limit": "^2.2.0",
|
|
12
12
|
"tslib": "^1.13.0"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"@yarnpkg/cli": "^3.2.0-rc.
|
|
16
|
-
"@yarnpkg/core": "^3.2.0-rc.
|
|
15
|
+
"@yarnpkg/cli": "^3.2.0-rc.6",
|
|
16
|
+
"@yarnpkg/core": "^3.2.0-rc.6"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@yarnpkg/cli": "^3.2.0-rc.
|
|
20
|
-
"@yarnpkg/core": "^3.2.0-rc.
|
|
19
|
+
"@yarnpkg/cli": "^3.2.0-rc.6",
|
|
20
|
+
"@yarnpkg/core": "^3.2.0-rc.6"
|
|
21
21
|
},
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|