8000 [package-extractor] Add support for linking bins when using the "scri… · atingmicrosoft/rushstack@075e022 · GitHub
[go: up one dir, main page]

Skip to content

Commit 075e022

Browse files
authored
[package-extractor] Add support for linking bins when using the "script" link creation mode (microsoft#4980)
* Add support for linking bins when using the "script" link creation mode * PR feedback * Add more logging * Fix bundle * More concurrency changes * Fix logging of bin links * Rush change * Change to use path.join in specific place that gets logged * Dedupe target folder resolution * Rush update * PR feedback * Add comment --------- Co-authored-by: Daniel <D4N14L@users.noreply.github.com>
1 parent 7f1ca5f commit 075e022

File tree

16 files changed

+402
-222
lines changed

16 files changed

+402
-222
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@rushstack/package-extractor",
5+
"comment": "Add bin linking support when calling the create-links.js script with the \"--link-bins\" parameter",
6+
"type": "minor"
7+
}
8+
],
9+
"packageName": "@rushstack/package-extractor"
10+
}

common/config/subspaces/build-tests-subspace/pnpm-lock.yaml

Lines changed: 13 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush.
22
{
3-
"pnpmShrinkwrapHash": "158eddd923799186d56f184f9ad0df261598e7ef",
3+
"pnpmShrinkwrapHash": "acf7c4f1de794be2d70dca29f989124eddfc541f",
44
"preferredVersionsHash": "ce857ea0536b894ec8f346aaea08cfd85a5af648",
5-
"packageJson 67F4 InjectedDependenciesHash": "780ed5a8b4dcd8c24fe68939798e54a2073c1c3c"
5+
"packageJsonInjectedDependenciesHash": "d8e3c0d28dcafaa568a71417fa3485ab58cbf829"
66
}

common/config/subspaces/default/pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libraries/package-extractor/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@pnpm/link-bins": "~5.3.7",
2121
"@rushstack/node-core-library": "workspace:*",
2222
"@rushstack/terminal": "workspace:*",
23+
"@rushstack/ts-command-line": "workspace:*",
2324
"ignore": "~5.1.6",
2425
"jszip": "~3.8.0",
2526
"minimatch": "~3.0.3",

libraries/package-extractor/src/PackageExtractor.ts

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import * as path from 'path';
55
import { type IMinimatch, Minimatch } from 'minimatch';
66
import semver from 'semver';
77
import npmPacklist from 'npm-packlist';
8-
import pnpmLinkBins from '@pnpm/link-bins';
98
import ignore, { type Ignore } from 'ignore';
109
import {
1110
Async,
@@ -20,8 +19,18 @@ import { Colorize, type ITerminal } from '@rushstack/terminal';
2019

2120
import { SymlinkAnalyzer, type ILinkInfo, type PathNode } from './SymlinkAnalyzer';
2221
import { AssetHandler } from './AssetHandler';
23-
import { matchesWithStar, remapSourcePathForTargetFolder, remapPathForExtractorMetadata } from './Utils';
24-
import { createLinksScriptFilename, scriptsFolderPath } from './PathConstants';
22+
import {
23+
matchesWithStar,
24+
remapSourcePathForTargetFolder,
25+
remapPathForExtractorMetadata,
26+
makeBinLinksAsync
27+
} from './Utils';
28+
import {
29+
CREATE_LINKS_SCRIPT_FILENAME,
30+
EXTRACTOR_METADATA_FILENAME,
31+
SCRIPTS_FOLDER_PATH
32+
} from './PathConstants';
33+
import { MAX_CONCURRENCY } from './scripts/createLinks/utilities/constants';
2534

2635
// (@types/npm-packlist is missing this API)
2736
declare module 'npm-packlist' {
@@ -479,7 +488,7 @@ export class PackageExtractor {
479488
await this._extractFolderAsync(folderToCopy, options, state);
480489
},
481490
{
482-
concurrency: 10
491+
concurrency: MAX_CONCURRENCY
483492
}
484493
);
485494

@@ -640,7 +649,7 @@ export class PackageExtractor {
640649
callback();
641650
},
642651
{
643-
concurrency: 10
652+
concurrency: MAX_CONCURRENCY
644653
}
645654
);
646655
}
@@ -799,7 +808,7 @@ export class PackageExtractor {
799808
}
800809
},
801810
{
802-
concurrency: 10
811+
concurrency: MAX_CONCURRENCY
803812
}
804813
);
805814
} else {
@@ -867,7 +876,7 @@ export class PackageExtractor {
867876
callback();
868877
},
869878
{
870-
concurrency: 10
879+
concurrency: MAX_CONCURRENCY
871880
}
872881
);
873882
}< 10000 /span>
@@ -884,14 +893,13 @@ export class PackageExtractor {
884893
options;
885894
const { projectConfigurationsByPath } = state;
886895

887-
const extractorMetadataFileName: string = 'extractor-metadata.json';
888896
const extractorMetadataFolderPath: string =
889897
linkCreation === 'script' && linkCreationScriptPath
890898
? path.dirname(path.resolve(targetRootFolder, linkCreationScriptPath))
891899
: targetRootFolder;
892900
const extractorMetadataFilePath: string = path.join(
893901
extractorMetadataFolderPath,
894-
extractorMetadataFileName
902+
EXTRACTOR_METADATA_FILENAME
895903
);
896904
const extractorMetadataJson: IExtractorMetadataJson = {
897905
mainProjectName,
@@ -932,41 +940,21 @@ export class PackageExtractor {
932940
private async _makeBinLinksAsync(options: IExtractorOptions, state: IExtractorState): Promise<void> {
933941
const { terminal } = options;
934942

935-
const extractedProjectFolders: string[] = Array.from(state.projectConfigurationsByPath.keys()).filter(
936-
(folderPath: string) => state.foldersToCopy.has(folderPath)
937-
);
938-
939-
await Async.forEachAsync(
940-
extractedProjectFolders,
941-
async (projectFolder: string) => {
942-
const extractedProjectFolder: string = remapSourcePathForTargetFolder({
943-
...options,
944-
sourcePath: projectFolder
945-
});
946-
const extractedProjectNodeModulesFolder: string = path.join(extractedProjectFolder, 'node_modules');
947-
const extractedProjectBinFolder: string = path.join(extractedProjectNodeModulesFolder, '.bin');
948-
949-
const linkedBinPackageNames: string[] = await pnpmLinkBins(
950-
extractedProjectNodeModulesFolder,
951-
extractedProjectBinFolder,
952-
{
953-
warn: (msg: string) => terminal.writeLine(Colorize.yellow(msg))
954-
}
943+
const extractedProjectFolderPaths: string[] = [];
944+
for (const folderPath of state.projectConfigurationsByPath.keys()) {
945+
if (state.foldersToCopy.has(folderPath)) {
946+
extractedProjectFolderPaths.push(
947+
remapSourcePathForTargetFolder({ ...options, sourcePath: folderPath })
955948
);
949+
}
950+
}
956951

957-
if (linkedBinPackageNames.length) {
958-
const binFolderItems: string[] =
959-
await FileSystem.readFolderItemNamesAsync(extractedProjectBinFolder);
960-
for (const binFolderItem of binFolderItems) {
961-
const binFilePath: string = path.resolve(extractedProjectBinFolder, binFolderItem);
962-
await state.assetHandler.includeAssetAsync({
963-
targetFilePath: binFilePath
964-
});
965-
}
966-
}
967-
},
952+
const binFilePaths: string[] = await makeBinLinksAsync(terminal, extractedProjectFolderPaths);
953+
await Async.forEachAsync(
954+
binFilePaths,
955+
(targetFilePath: string) => state.assetHandler.includeAssetAsync({ targetFilePath }),
968956
{
969-
concurrency: 10
957+
concurrency: MAX_CONCURRENCY
970958
}
971959
);
972960
}
@@ -978,11 +966,11 @@ export class PackageExtractor {
978966
const { terminal, targetRootFolder, linkCreationScriptPath } = options;
979967
const { assetHandler } = state;
980968

981-
terminal.writeLine(`Creating ${createLinksScriptFilename}`);
982-
const createLinksSourceFilePath: string = `${scriptsFolderPath}/${createLinksScriptFilename}`;
969+
terminal.writeLine(`Creating ${CREATE_LINKS_SCRIPT_FILENAME}`);
970+
const createLinksSourceFilePath: string = `${SCRIPTS_FOLDER_PATH}/${CREATE_LINKS_SCRIPT_FILENAME}`;
983971
const createLinksTargetFilePath: string = path.resolve(
984972
targetRootFolder,
985-
linkCreationScriptPath || createLinksScriptFilename
973+
linkCreationScriptPath || CREATE_LINKS_SCRIPT_FILENAME
986974
);
987975
let createLinksScriptContent: string = await FileSystem.readFileAsync(createLinksSourceFilePath);
988976
createLinksScriptContent = createLinksScriptContent.replace(

libraries/package-extractor/src/PathConstants.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
import { PackageJsonLookup } from '@rushstack/node-core-library';
55

6+
export const CREATE_LINKS_SCRIPT_FILENAME: 'create-links.js' = 'create-links.js';
7+
8+
export const EXTRACTOR_METADATA_FILENAME: 'extractor-metadata.json' = 'extractor-metadata.json';
9+
610
const packageExtractorFolderRootPath: string = PackageJsonLookup.instance.tryGetPackageFolderFor(__dirname)!;
7-
export const createLinksScriptFilename: 'create-links.js' = 'create-links.js';
8-
export const scriptsFolderPath: string = `${packageExtractorFolderRootPath}/dist/scripts`;
11+
export const SCRIPTS_FOLDER_PATH: string = `${packageExtractorFolderRootPath}/dist/scripts`;

libraries/package-extractor/src/Utils.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
// See LICENSE in the project root for license information.
33

44
import path from 'node:path';
5-
import { Path, Text } from '@rushstack/node-core-library';
5+
import pnpmLinkBins from '@pnpm/link-bins';
6+
import { Async, FileSystem, Path, Text } from '@rushstack/node-core-library';
7+
import { Colorize, type ITerminal } from '@rushstack/terminal';
8+
import { MAX_CONCURRENCY } from './scripts/createLinks/utilities/constants';
69

710
export function matchesWithStar(patternWithStar: string, input: string): boolean {
811
// Map "@types/*" --> "^\@types\/.*$"
@@ -54,3 +57,47 @@ export function remapPathForExtractorMetadata(folderPath: string, filePath: stri
5457
}
5558
return Path.convertToSlashes(relativePath);
5659
}
60+
61+
/**
62+
* Creates the .bin files for the extracted projects and returns the paths to the created .bin files.
63+
*
64+
* @param terminal - The terminal to write to
65+
* @param extractedProjectFolderPaths - The paths to the extracted projects
66+
*/
67+
export async function makeBinLinksAsync(
68+
terminal: ITerminal,
69+
extractedProjectFolderPaths: string[]
70+
): Promise<string[]> {
71+
const binFilePaths: string[] = [];
72+
await Async.forEachAsync(
73+
extractedProjectFolderPaths,
74+
async (extractedProjectFolderPath: string) => {
75+
const extractedProjectNodeModulesFolderPath: string = `${extractedProjectFolderPath}/node_modules`;
76+
const extractedProjectBinFolderPath: string = `${extractedProjectNodeModulesFolderPath}/.bin`;
77+
78+
const linkedBinPackageNames: string[] = await pnpmLinkBins(
79+
extractedProjectNodeModulesFolderPath,
80+
extractedProjectBinFolderPath,
81+
{
82+
warn: (msg: string) => terminal.writeLine(Colorize.yellow(msg))
83+
}
84+
);
85+
86+
if (linkedBinPackageNames.length) {
87+
const binFolderItems: string[] = await FileSystem.readFolderItemNamesAsync(
88+
extractedProjectBinFolderPath
89+
);
90+
for (const binFolderItem of binFolderItems) {
91+
const binFilePath: string = `${extractedProjectBinFolderPath}/${binFolderItem}`;
92+
terminal.writeVerboseLine(`Created .bin file: ${binFilePath}`);
93+
binFilePaths.push(binFilePath);
94+
}
95+
}
96+
},
97+
{
98+
concurrency: MAX_CONCURRENCY
99+
}
100+
);
101+
102+
return binFilePaths;
103+
}

0 commit comments

Comments
 (0)
0