lockfile-subset 1.2.1 → 1.3.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.
- package/dist/index.mjs +140 -61
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,33 +1,72 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { join, resolve } from "path";
|
|
2
|
+
import { basename, dirname, join, relative, resolve, sep } from "path";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4
4
|
import { execSync } from "child_process";
|
|
5
5
|
import { createRequire } from "module";
|
|
6
6
|
import Arborist from "@npmcli/arborist";
|
|
7
7
|
import yaml from "js-yaml";
|
|
8
|
+
//#region src/workspace-path.ts
|
|
9
|
+
/**
|
|
10
|
+
* Normalize a workspace/importer path to a forward-slash relative key.
|
|
11
|
+
* Returns "." for the root (empty input, ".", "./").
|
|
12
|
+
*/
|
|
13
|
+
function normalizeWorkspacePath(p) {
|
|
14
|
+
if (!p || p === "." || p === "./") return ".";
|
|
15
|
+
return p.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
8
18
|
//#region src/extract.ts
|
|
9
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Rewrite a package-lock.json location key so the output is a standalone project.
|
|
21
|
+
* Locations inside the chosen workspace get their workspace prefix stripped;
|
|
22
|
+
* hoisted entries at the root stay where they are.
|
|
23
|
+
*/
|
|
24
|
+
function rewritePackageLocation(location, workspacePath) {
|
|
25
|
+
if (workspacePath === ".") return location;
|
|
26
|
+
if (location === workspacePath) return "";
|
|
27
|
+
const prefix = workspacePath + "/";
|
|
28
|
+
if (location.startsWith(prefix)) return location.slice(prefix.length);
|
|
29
|
+
return location;
|
|
30
|
+
}
|
|
31
|
+
async function extractSubset({ projectPath, packageNames, includeOptional = true, workspacePath = "." }) {
|
|
10
32
|
const tree = await new Arborist({ path: projectPath }).loadVirtual();
|
|
11
33
|
const originalLockfileVersion = tree.meta.originalLockfileVersion;
|
|
12
34
|
if (originalLockfileVersion < 2) throw new Error(`Lockfile version ${originalLockfileVersion} is not supported. Please upgrade to npm 7+ (lockfile v2/v3) by running: npm install --package-lock-only`);
|
|
35
|
+
const normalizedWorkspace = normalizeWorkspacePath(workspacePath);
|
|
36
|
+
let startNode = tree;
|
|
37
|
+
if (normalizedWorkspace !== ".") {
|
|
38
|
+
let found;
|
|
39
|
+
for (const child of tree.fsChildren) if (child.location === normalizedWorkspace) {
|
|
40
|
+
found = child;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
if (!found) {
|
|
44
|
+
const available = [...tree.fsChildren].map((c) => c.location).join(", ");
|
|
45
|
+
throw new Error(`Workspace "${normalizedWorkspace}" not found in package-lock.json. Available workspaces: ${available || "(none)"}`);
|
|
46
|
+
}
|
|
47
|
+
startNode = found;
|
|
48
|
+
}
|
|
13
49
|
const keep = /* @__PURE__ */ new Set();
|
|
14
50
|
for (const name of packageNames) {
|
|
15
|
-
const edge =
|
|
51
|
+
const edge = startNode.edgesOut.get(name);
|
|
16
52
|
if (!edge?.to) throw new Error(`Package "${name}" not found in lockfile`);
|
|
53
|
+
if (edge.type === "workspace" || edge.to.isWorkspace) throw new Error(`Package "${name}" resolves to a workspace, not a published package`);
|
|
17
54
|
const queue = [edge.to];
|
|
18
55
|
while (queue.length > 0) {
|
|
19
56
|
const node = queue.shift();
|
|
20
57
|
if (keep.has(node)) continue;
|
|
58
|
+
if (node.isWorkspace) continue;
|
|
21
59
|
keep.add(node);
|
|
22
60
|
for (const e of node.edgesOut.values()) {
|
|
23
61
|
if (e.type === "dev") continue;
|
|
62
|
+
if (e.type === "workspace") continue;
|
|
24
63
|
if (e.type === "optional" && !includeOptional) continue;
|
|
25
|
-
if (e.to && !keep.has(e.to)) queue.push(e.to);
|
|
64
|
+
if (e.to && !e.to.isWorkspace && !keep.has(e.to)) queue.push(e.to);
|
|
26
65
|
}
|
|
27
66
|
}
|
|
28
67
|
}
|
|
29
68
|
const dependencies = {};
|
|
30
|
-
for (const name of packageNames) dependencies[name] =
|
|
69
|
+
for (const name of packageNames) dependencies[name] = startNode.edgesOut.get(name).to.version;
|
|
31
70
|
const subsetPackages = {};
|
|
32
71
|
subsetPackages[""] = {
|
|
33
72
|
name: "lockfile-subset-output",
|
|
@@ -36,8 +75,10 @@ async function extractSubset({ projectPath, packageNames, includeOptional = true
|
|
|
36
75
|
};
|
|
37
76
|
const originalPackages = tree.meta.data.packages;
|
|
38
77
|
for (const node of keep) {
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
78
|
+
const original = originalPackages[node.location];
|
|
79
|
+
if (!original) continue;
|
|
80
|
+
const rewritten = rewritePackageLocation(node.location, normalizedWorkspace);
|
|
81
|
+
subsetPackages[rewritten] = original;
|
|
41
82
|
}
|
|
42
83
|
const collected = [...keep].map((node) => ({
|
|
43
84
|
name: node.name,
|
|
@@ -77,21 +118,31 @@ function parseSnapshotKey(key) {
|
|
|
77
118
|
function snapshotKey(name, version) {
|
|
78
119
|
return `${name}@${version}`;
|
|
79
120
|
}
|
|
80
|
-
async function extractPnpmSubset({ projectPath, packageNames, includeOptional = true }) {
|
|
121
|
+
async function extractPnpmSubset({ projectPath, packageNames, includeOptional = true, workspacePath = "." }) {
|
|
81
122
|
const content = readFileSync(join(projectPath, "pnpm-lock.yaml"), "utf8");
|
|
82
123
|
const lockfile = yaml.load(content);
|
|
83
124
|
if (!lockfile.lockfileVersion || !String(lockfile.lockfileVersion).startsWith("9")) throw new Error(`pnpm lockfile version ${lockfile.lockfileVersion} is not supported. Please upgrade to pnpm 9+ (lockfile v9).`);
|
|
84
|
-
const
|
|
85
|
-
|
|
125
|
+
const importerKey = normalizeWorkspacePath(workspacePath);
|
|
126
|
+
const importer = lockfile.importers[importerKey];
|
|
127
|
+
if (!importer) {
|
|
128
|
+
const available = Object.keys(lockfile.importers).join(", ");
|
|
129
|
+
throw new Error(`Importer "${importerKey}" not found in pnpm-lock.yaml. Available importers: ${available}`);
|
|
130
|
+
}
|
|
86
131
|
const rootDeps = {};
|
|
87
|
-
|
|
88
|
-
|
|
132
|
+
for (const info of [importer.dependencies, importer.optionalDependencies]) {
|
|
133
|
+
if (!info) continue;
|
|
134
|
+
for (const [name, dep] of Object.entries(info)) rootDeps[name] = {
|
|
135
|
+
specifier: dep.specifier,
|
|
136
|
+
version: dep.version
|
|
137
|
+
};
|
|
138
|
+
}
|
|
89
139
|
const keepSnapshots = /* @__PURE__ */ new Set();
|
|
90
140
|
const keepPackages = /* @__PURE__ */ new Set();
|
|
91
141
|
for (const name of packageNames) {
|
|
92
|
-
const
|
|
93
|
-
if (!
|
|
94
|
-
|
|
142
|
+
const dep = rootDeps[name];
|
|
143
|
+
if (!dep) throw new Error(`Package "${name}" not found in pnpm-lock.yaml`);
|
|
144
|
+
if (dep.version.startsWith("link:")) throw new Error(`Package "${name}" resolves to a workspace (${dep.version}), not a published package`);
|
|
145
|
+
const queue = [snapshotKey(name, dep.version)];
|
|
95
146
|
while (queue.length > 0) {
|
|
96
147
|
const current = queue.shift();
|
|
97
148
|
if (keepSnapshots.has(current)) continue;
|
|
@@ -101,25 +152,27 @@ async function extractPnpmSubset({ projectPath, packageNames, includeOptional =
|
|
|
101
152
|
const snapshot = lockfile.snapshots[current];
|
|
102
153
|
if (!snapshot) continue;
|
|
103
154
|
if (snapshot.dependencies) for (const [depName, depVersion] of Object.entries(snapshot.dependencies)) {
|
|
155
|
+
if (depVersion.startsWith("link:")) continue;
|
|
104
156
|
const depKey = snapshotKey(depName, depVersion);
|
|
105
157
|
if (!keepSnapshots.has(depKey)) queue.push(depKey);
|
|
106
158
|
}
|
|
107
159
|
if (includeOptional && snapshot.optionalDependencies) for (const [depName, depVersion] of Object.entries(snapshot.optionalDependencies)) {
|
|
160
|
+
if (depVersion.startsWith("link:")) continue;
|
|
108
161
|
const depKey = snapshotKey(depName, depVersion);
|
|
109
162
|
if (!keepSnapshots.has(depKey)) queue.push(depKey);
|
|
110
163
|
}
|
|
111
164
|
}
|
|
112
165
|
}
|
|
113
166
|
const dependencies = {};
|
|
114
|
-
for (const name of packageNames) dependencies[name] =
|
|
167
|
+
for (const name of packageNames) dependencies[name] = rootDeps[name].specifier;
|
|
115
168
|
const subsetPackages = {};
|
|
116
169
|
for (const key of keepPackages) if (lockfile.packages[key]) subsetPackages[key] = lockfile.packages[key];
|
|
117
170
|
const subsetSnapshots = {};
|
|
118
171
|
for (const key of keepSnapshots) if (lockfile.snapshots[key]) subsetSnapshots[key] = lockfile.snapshots[key];
|
|
119
172
|
const subsetImporter = { dependencies: {} };
|
|
120
173
|
for (const name of packageNames) subsetImporter.dependencies[name] = {
|
|
121
|
-
specifier:
|
|
122
|
-
version: rootDeps[name]
|
|
174
|
+
specifier: rootDeps[name].specifier,
|
|
175
|
+
version: rootDeps[name].version
|
|
123
176
|
};
|
|
124
177
|
const collected = [...keepPackages].map((key) => {
|
|
125
178
|
const parsed = parseSnapshotKey(key);
|
|
@@ -151,11 +204,11 @@ const { parse: parseYarnLockV1, stringify: stringifyYarnLockV1 } = createRequire
|
|
|
151
204
|
function detectYarnVersion(content) {
|
|
152
205
|
return content.includes("# yarn lockfile v1") ? 1 : 2;
|
|
153
206
|
}
|
|
154
|
-
function extractV1({ projectPath, packageNames, includeOptional, lockfileContent }) {
|
|
207
|
+
function extractV1({ projectPath, packageNames, includeOptional, lockfileContent, workspacePath }) {
|
|
155
208
|
const parsed = parseYarnLockV1(lockfileContent);
|
|
156
209
|
if (parsed.type !== "success") throw new Error(`Failed to parse yarn.lock: ${parsed.type}`);
|
|
157
210
|
const lockfile = parsed.object;
|
|
158
|
-
const pkgJsonPath = join(projectPath, "package.json");
|
|
211
|
+
const pkgJsonPath = join(projectPath, workspacePath, "package.json");
|
|
159
212
|
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf8"));
|
|
160
213
|
const allDeps = {
|
|
161
214
|
...pkgJson.dependencies,
|
|
@@ -166,6 +219,7 @@ function extractV1({ projectPath, packageNames, includeOptional, lockfileContent
|
|
|
166
219
|
for (const name of packageNames) {
|
|
167
220
|
const range = allDeps[name];
|
|
168
221
|
if (!range) throw new Error(`Package "${name}" not found in yarn.lock`);
|
|
222
|
+
if (!lockfile[`${name}@${range}`]) throw new Error(`Package "${name}@${range}" has no lockfile entry. It is likely a workspace dependency, not a published package.`);
|
|
169
223
|
const queue = [`${name}@${range}`];
|
|
170
224
|
while (queue.length > 0) {
|
|
171
225
|
const key = queue.shift();
|
|
@@ -190,7 +244,7 @@ function extractV1({ projectPath, packageNames, includeOptional, lockfileContent
|
|
|
190
244
|
const subset = {};
|
|
191
245
|
for (const key of keepKeys) subset[key] = lockfile[key];
|
|
192
246
|
const dependencies = {};
|
|
193
|
-
for (const name of packageNames) dependencies[name] =
|
|
247
|
+
for (const name of packageNames) dependencies[name] = allDeps[name];
|
|
194
248
|
const seen = /* @__PURE__ */ new Set();
|
|
195
249
|
const deduped = collected.filter((c) => {
|
|
196
250
|
const key = `${c.name}@${c.version}`;
|
|
@@ -210,7 +264,7 @@ function extractV1({ projectPath, packageNames, includeOptional, lockfileContent
|
|
|
210
264
|
collected: deduped
|
|
211
265
|
};
|
|
212
266
|
}
|
|
213
|
-
function extractBerry({ projectPath, packageNames, includeOptional, lockfileContent }) {
|
|
267
|
+
function extractBerry({ projectPath, packageNames, includeOptional, lockfileContent, workspacePath }) {
|
|
214
268
|
const lockfile = yaml.load(lockfileContent);
|
|
215
269
|
const descriptorMap = /* @__PURE__ */ new Map();
|
|
216
270
|
for (const [compoundKey, entry] of Object.entries(lockfile)) {
|
|
@@ -221,7 +275,7 @@ function extractBerry({ projectPath, packageNames, includeOptional, lockfileCont
|
|
|
221
275
|
originalKey: compoundKey
|
|
222
276
|
});
|
|
223
277
|
}
|
|
224
|
-
const pkgJsonPath = join(projectPath, "package.json");
|
|
278
|
+
const pkgJsonPath = join(projectPath, workspacePath, "package.json");
|
|
225
279
|
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf8"));
|
|
226
280
|
const allDeps = {
|
|
227
281
|
...pkgJson.dependencies,
|
|
@@ -233,6 +287,7 @@ function extractBerry({ projectPath, packageNames, includeOptional, lockfileCont
|
|
|
233
287
|
for (const name of packageNames) {
|
|
234
288
|
const range = allDeps[name];
|
|
235
289
|
if (!range) throw new Error(`Package "${name}" not found in yarn.lock`);
|
|
290
|
+
if (range.startsWith("workspace:")) throw new Error(`Package "${name}" resolves to a workspace, not a published package`);
|
|
236
291
|
const queue = [`${name}@npm:${range}`];
|
|
237
292
|
while (queue.length > 0) {
|
|
238
293
|
const desc = queue.shift();
|
|
@@ -246,20 +301,19 @@ function extractBerry({ projectPath, packageNames, includeOptional, lockfileCont
|
|
|
246
301
|
version: match.entry.version
|
|
247
302
|
});
|
|
248
303
|
if (match.entry.dependencies) for (const [depName, depRange] of Object.entries(match.entry.dependencies)) {
|
|
304
|
+
if (depRange.startsWith("workspace:")) continue;
|
|
249
305
|
const depDesc = `${depName}@${depRange}`;
|
|
250
306
|
if (!visited.has(depDesc)) queue.push(depDesc);
|
|
251
307
|
}
|
|
252
308
|
if (includeOptional && match.entry.optionalDependencies) for (const [depName, depRange] of Object.entries(match.entry.optionalDependencies)) {
|
|
309
|
+
if (depRange.startsWith("workspace:")) continue;
|
|
253
310
|
const depDesc = `${depName}@${depRange}`;
|
|
254
311
|
if (!visited.has(depDesc)) queue.push(depDesc);
|
|
255
312
|
}
|
|
256
313
|
}
|
|
257
314
|
}
|
|
258
315
|
const dependencies = {};
|
|
259
|
-
for (const name of packageNames)
|
|
260
|
-
const descriptor = `${name}@npm:${allDeps[name]}`;
|
|
261
|
-
dependencies[name] = descriptorMap.get(descriptor).entry.version;
|
|
262
|
-
}
|
|
316
|
+
for (const name of packageNames) dependencies[name] = allDeps[name];
|
|
263
317
|
const lines = [];
|
|
264
318
|
lines.push("# This file is generated by running \"yarn install\" inside your project.");
|
|
265
319
|
lines.push("# Manual changes might be lost - proceed with caution!");
|
|
@@ -328,19 +382,23 @@ function parseDescriptorName(descriptor) {
|
|
|
328
382
|
if (lastAt > 0) return descriptor.slice(0, lastAt);
|
|
329
383
|
return descriptor;
|
|
330
384
|
}
|
|
331
|
-
async function extractYarnSubset({ projectPath, packageNames, includeOptional = true }) {
|
|
385
|
+
async function extractYarnSubset({ projectPath, packageNames, includeOptional = true, workspacePath = "." }) {
|
|
332
386
|
const lockfileContent = readFileSync(join(projectPath, "yarn.lock"), "utf8");
|
|
333
|
-
|
|
387
|
+
const version = detectYarnVersion(lockfileContent);
|
|
388
|
+
const normalizedWorkspace = normalizeWorkspacePath(workspacePath);
|
|
389
|
+
if (version === 1) return extractV1({
|
|
334
390
|
projectPath,
|
|
335
391
|
packageNames,
|
|
336
392
|
includeOptional,
|
|
337
|
-
lockfileContent
|
|
393
|
+
lockfileContent,
|
|
394
|
+
workspacePath: normalizedWorkspace
|
|
338
395
|
});
|
|
339
396
|
else return extractBerry({
|
|
340
397
|
projectPath,
|
|
341
398
|
packageNames,
|
|
342
399
|
includeOptional,
|
|
343
|
-
lockfileContent
|
|
400
|
+
lockfileContent,
|
|
401
|
+
workspacePath: normalizedWorkspace
|
|
344
402
|
});
|
|
345
403
|
}
|
|
346
404
|
//#endregion
|
|
@@ -411,37 +469,48 @@ function parseArgs(argv) {
|
|
|
411
469
|
}
|
|
412
470
|
return args;
|
|
413
471
|
}
|
|
472
|
+
const LOCKFILE_BASENAMES = {
|
|
473
|
+
"pnpm-lock.yaml": "pnpm",
|
|
474
|
+
"yarn.lock": "yarn",
|
|
475
|
+
"package-lock.json": "npm"
|
|
476
|
+
};
|
|
477
|
+
/** Walk up from `start` looking for any known lockfile. Returns null if none found. */
|
|
478
|
+
function findLockfileUpwards(start) {
|
|
479
|
+
let dir = start;
|
|
480
|
+
while (true) {
|
|
481
|
+
for (const [name, type] of Object.entries(LOCKFILE_BASENAMES)) if (existsSync(resolve(dir, name))) return {
|
|
482
|
+
projectPath: dir,
|
|
483
|
+
type
|
|
484
|
+
};
|
|
485
|
+
const parent = dirname(dir);
|
|
486
|
+
if (parent === dir) return null;
|
|
487
|
+
dir = parent;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
414
490
|
function resolveLockfile(lockfilePath) {
|
|
415
491
|
if (!lockfilePath) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
};
|
|
420
|
-
if (existsSync(resolve("yarn.lock"))) return {
|
|
421
|
-
projectPath: resolve("."),
|
|
422
|
-
type: "yarn"
|
|
423
|
-
};
|
|
424
|
-
if (existsSync(resolve("package-lock.json"))) return {
|
|
425
|
-
projectPath: resolve("."),
|
|
426
|
-
type: "npm"
|
|
427
|
-
};
|
|
428
|
-
throw new Error("No lockfile found in current directory. Expected package-lock.json, pnpm-lock.yaml, or yarn.lock.");
|
|
492
|
+
const found = findLockfileUpwards(resolve("."));
|
|
493
|
+
if (found) return found;
|
|
494
|
+
throw new Error("No lockfile found in current directory or any parent. Expected package-lock.json, pnpm-lock.yaml, or yarn.lock.");
|
|
429
495
|
}
|
|
430
496
|
const resolved = resolve(lockfilePath);
|
|
431
|
-
const
|
|
432
|
-
if (
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if (basename === "yarn.lock") return {
|
|
437
|
-
projectPath: resolve(resolved, ".."),
|
|
438
|
-
type: "yarn"
|
|
439
|
-
};
|
|
440
|
-
if (basename === "package-lock.json") return {
|
|
441
|
-
projectPath: resolve(resolved, ".."),
|
|
442
|
-
type: "npm"
|
|
497
|
+
const type = LOCKFILE_BASENAMES[basename(resolved)];
|
|
498
|
+
if (!type) throw new Error(`Invalid lockfile path: ${lockfilePath}. Expected a path to package-lock.json, pnpm-lock.yaml, or yarn.lock.`);
|
|
499
|
+
return {
|
|
500
|
+
projectPath: dirname(resolved),
|
|
501
|
+
type
|
|
443
502
|
};
|
|
444
|
-
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Resolve the workspace path (relative to projectPath, forward slashes).
|
|
506
|
+
* Inferred from process.cwd() vs the lockfile's project directory: if cwd
|
|
507
|
+
* sits inside a sub-workspace, that path is used; otherwise "." (root).
|
|
508
|
+
*/
|
|
509
|
+
function resolveWorkspacePath(projectPath) {
|
|
510
|
+
const rel = relative(projectPath, resolve("."));
|
|
511
|
+
if (rel === "" || rel === ".") return ".";
|
|
512
|
+
if (rel.startsWith("..")) return ".";
|
|
513
|
+
return rel.split(sep).join("/");
|
|
445
514
|
}
|
|
446
515
|
const HELP = `
|
|
447
516
|
lockfile-subset <packages...> [options]
|
|
@@ -453,7 +522,7 @@ Arguments:
|
|
|
453
522
|
packages Package names to extract (one or more, space-separated)
|
|
454
523
|
|
|
455
524
|
Options:
|
|
456
|
-
--lockfile, -l <path> Path to lockfile (auto-detected from cwd
|
|
525
|
+
--lockfile, -l <path> Path to lockfile (auto-detected by walking up from cwd)
|
|
457
526
|
--output, -o <dir> Output directory (default: ./lockfile-subset-output)
|
|
458
527
|
--no-optional Exclude optional dependencies
|
|
459
528
|
--install Run npm ci / pnpm install / yarn install after generating
|
|
@@ -467,6 +536,11 @@ Examples:
|
|
|
467
536
|
lockfile-subset @prisma/client sharp -l /build/package-lock.json
|
|
468
537
|
lockfile-subset @prisma/client sharp -l pnpm-lock.yaml --install
|
|
469
538
|
lockfile-subset chalk --dry-run
|
|
539
|
+
|
|
540
|
+
Monorepos: cd into the target workspace and run as usual.
|
|
541
|
+
The lockfile is found by walking up from the current directory, and the
|
|
542
|
+
sub-workspace is inferred from cwd relative to the lockfile.
|
|
543
|
+
cd apps/web && lockfile-subset next
|
|
470
544
|
`.trim();
|
|
471
545
|
async function main() {
|
|
472
546
|
const args = parseArgs(process.argv.slice(2));
|
|
@@ -484,22 +558,27 @@ async function main() {
|
|
|
484
558
|
process.exit(1);
|
|
485
559
|
}
|
|
486
560
|
const { projectPath, type } = resolveLockfile(args.lockfile);
|
|
561
|
+
const workspacePath = resolveWorkspacePath(projectPath);
|
|
487
562
|
const outputDir = resolve(args.output);
|
|
563
|
+
if (workspacePath !== ".") console.log(`Using workspace: ${workspacePath} (lockfile root: ${projectPath})`);
|
|
488
564
|
let result;
|
|
489
565
|
if (type === "pnpm") result = await extractPnpmSubset({
|
|
490
566
|
projectPath,
|
|
491
567
|
packageNames: args.packages,
|
|
492
|
-
includeOptional: args.includeOptional
|
|
568
|
+
includeOptional: args.includeOptional,
|
|
569
|
+
workspacePath
|
|
493
570
|
});
|
|
494
571
|
else if (type === "yarn") result = await extractYarnSubset({
|
|
495
572
|
projectPath,
|
|
496
573
|
packageNames: args.packages,
|
|
497
|
-
includeOptional: args.includeOptional
|
|
574
|
+
includeOptional: args.includeOptional,
|
|
575
|
+
workspacePath
|
|
498
576
|
});
|
|
499
577
|
else result = await extractSubset({
|
|
500
578
|
projectPath,
|
|
501
579
|
packageNames: args.packages,
|
|
502
|
-
includeOptional: args.includeOptional
|
|
580
|
+
includeOptional: args.includeOptional,
|
|
581
|
+
workspacePath
|
|
503
582
|
});
|
|
504
583
|
console.log(`Collected ${result.collected.length} packages (${args.packages.length} direct, ${result.collected.length - args.packages.length} transitive)`);
|
|
505
584
|
if (args.dryRun) {
|
package/package.json
CHANGED