From f518c90fdc38c14bdfebcc6cd423d3da12b9d464 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:47:03 +0000 Subject: [PATCH 1/3] Enhance _collectFoldersAsync to process all starting folders in one queue and add pnpmNodeModulesHoistingEnabled option Agent-Logs-Url: https://github.com/microsoft/rushstack/sessions/483711d5-f1e0-4f69-b1b1-445230d9c33f Co-authored-by: dmichon-msft <26827560+dmichon-msft@users.noreply.github.com> --- common/reviews/api/package-extractor.api.md | 1 + .../package-extractor/src/PackageExtractor.ts | 24 +++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/common/reviews/api/package-extractor.api.md b/common/reviews/api/package-extractor.api.md index f0503a30d4f..1b0cfb0139c 100644 --- a/common/reviews/api/package-extractor.api.md +++ b/common/reviews/api/package-extractor.api.md @@ -58,6 +58,7 @@ export interface IExtractorProjectConfiguration { // @public export interface IExtractorSubspace { pnpmInstallFolder?: string; + pnpmNodeModulesHoistingEnabled?: boolean; subspaceName: string; transformPackageJson?: (packageJson: IPackageJson) => IPackageJson; } diff --git a/libraries/package-extractor/src/PackageExtractor.ts b/libraries/package-extractor/src/PackageExtractor.ts index 1e7c3602111..07016eb68a1 100644 --- a/libraries/package-extractor/src/PackageExtractor.ts +++ b/libraries/package-extractor/src/PackageExtractor.ts @@ -108,6 +108,12 @@ export interface IExtractorSubspace { * transform the package.json prior to extraction. */ transformPackageJson?: (packageJson: IPackageJson) => IPackageJson; + /** + * Whether PNPM's `node-modules.hoisting` is enabled for this subspace. When set to `false`, + * the extractor will skip looking for hoisted packages in the PNPM virtual store, since no + * hoisting symlinks will exist. Default is `true`. + */ + pnpmNodeModulesHoistingEnabled?: boolean; } interface IExtractorState { @@ -489,10 +495,12 @@ export class PackageExtractor { } } + const startingFolders: string[] = []; for (const { projectName, projectFolder } of includedProjectsSet) { terminal.writeLine(Colorize.cyan(`Analyzing project: ${projectName}`)); - await this._collectFoldersAsync(projectFolder, options, state); + startingFolders.push(projectFolder); } + await this._collectFoldersAsync(startingFolders, options, state); if (!createArchiveOnly) { terminal.writeLine(`Copying folders to target folder "${targetRootFolder}"`); @@ -524,14 +532,14 @@ export class PackageExtractor { * Recursively crawl the node_modules dependencies and collect the result in IExtractorState.foldersToCopy. */ private async _collectFoldersAsync( - packageJsonFolder: string, + packageJsonFolders: string[], options: IExtractorOptions, state: IExtractorState ): Promise { const { terminal, subspaces } = options; const { projectConfigurationsByPath } = state; - const packageJsonFolderPathQueue: AsyncQueue = new AsyncQueue([packageJsonFolder]); + const packageJsonFolderPathQueue: AsyncQueue = new AsyncQueue(packageJsonFolders); await Async.forEachAsync( packageJsonFolderPathQueue, @@ -624,9 +632,15 @@ export class PackageExtractor { // Replicate the links to the virtual store. Note that if the package has not been hoisted by // PNPM, the package will not be resolvable from here. - // Only apply this logic for packages that were actually installed under the common/temp folder. + // Only apply this logic for packages that were actually installed under the common/temp folder, + // and only when hoisting is enabled for the subspace. const realPnpmInstallFolder: string | undefined = targetSubspace?.pnpmInstallFolder; - if (realPnpmInstallFolder && Path.isUnder(packageJsonFolderPath, realPnpmInstallFolder)) { + const hoistingEnabled: boolean = targetSubspace?.pnpmNodeModulesHoistingEnabled !== false; + if ( + hoistingEnabled && + realPnpmInstallFolder && + Path.isUnder(packageJsonFolderPath, realPnpmInstallFolder) + ) { try { // The PNPM virtual store links are created in this folder. We will resolve the current package // from that location and collect any additional links encountered along the way. From 5659b42ccd412805b7fa66879b9915d031662e94 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:50:21 +0000 Subject: [PATCH 2/3] Fix TSDoc comment for pnpmNodeModulesHoistingEnabled Agent-Logs-Url: https://github.com/microsoft/rushstack/sessions/483711d5-f1e0-4f69-b1b1-445230d9c33f Co-authored-by: dmichon-msft <26827560+dmichon-msft@users.noreply.github.com> --- libraries/package-extractor/src/PackageExtractor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/package-extractor/src/PackageExtractor.ts b/libraries/package-extractor/src/PackageExtractor.ts index 07016eb68a1..c2f4c790f7f 100644 --- a/libraries/package-extractor/src/PackageExtractor.ts +++ b/libraries/package-extractor/src/PackageExtractor.ts @@ -109,7 +109,7 @@ export interface IExtractorSubspace { */ transformPackageJson?: (packageJson: IPackageJson) => IPackageJson; /** - * Whether PNPM's `node-modules.hoisting` is enabled for this subspace. When set to `false`, + * Whether PNPM hoisting is enabled for this subspace. When set to `false`, * the extractor will skip looking for hoisted packages in the PNPM virtual store, since no * hoisting symlinks will exist. Default is `true`. */ From bca6ca2922eba38c061003d755b8108c6a40e5d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 23:56:54 +0000 Subject: [PATCH 3/3] Add change file for @rushstack/package-extractor (minor) Agent-Logs-Url: https://github.com/microsoft/rushstack/sessions/bdcb8673-e8f6-480c-a999-44737579f43f Co-authored-by: dmichon-msft <26827560+dmichon-msft@users.noreply.github.com> --- ...age-extractor-collect-folders_2026-04-08-23-56.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@rushstack/package-extractor/enhance-package-extractor-collect-folders_2026-04-08-23-56.json diff --git a/common/changes/@rushstack/package-extractor/enhance-package-extractor-collect-folders_2026-04-08-23-56.json b/common/changes/@rushstack/package-extractor/enhance-package-extractor-collect-folders_2026-04-08-23-56.json new file mode 100644 index 00000000000..4cd9425aef0 --- /dev/null +++ b/common/changes/@rushstack/package-extractor/enhance-package-extractor-collect-folders_2026-04-08-23-56.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/package-extractor", + "comment": "Update _collectFoldersAsync to process all starting folders in a single shared queue instead of serially. Add pnpmNodeModulesHoistingEnabled option to IExtractorSubspace to skip virtual store hoisting lookup when hoisting is disabled.", + "type": "minor" + } + ], + "packageName": "@rushstack/package-extractor" +}