@@ -5,9 +5,31 @@ import type { ChildProcess } from 'node:child_process';
55
66import { Async , Executable , JsonFile } from '@rushstack/node-core-library' ;
77import type { ITerminal } from '@rushstack/terminal' ;
8- import { DependencyType , RushConfiguration , type CommonVersionsConfiguration } from '@microsoft/rush-lib' ;
8+ import { DependencyType , RushConfiguration } from '@microsoft/rush-lib' ;
9+ import type { IRushConfigurationJson } from '@microsoft/rush-lib/lib/api/RushConfiguration' ;
910import { CommandLineAction } from '@rushstack/ts-command-line' ;
1011
12+ async function _getLatestPublishedVersionAsync ( terminal : ITerminal , packageName : string ) : Promise < string > {
13+ return await new Promise ( ( resolve : ( result : string ) => void , reject : ( error : Error ) => void ) => {
14+ const childProcess : ChildProcess = Executable . spawn ( 'npm' , [ 'view' , packageName , 'version' ] , {
15+ stdio : [ 'ignore' , 'pipe' , 'pipe' ]
16+ } ) ;
17+ const stdoutBuffer : string [ ] = [ ] ;
18+ childProcess . stdout ! . on ( 'data' , ( chunk ) => stdoutBuffer . push ( chunk ) ) ;
19+ childProcess . on ( 'close' , ( exitCode : number | null , signal : NodeJS . Signals | null ) => {
20+ if ( exitCode ) {
21+ reject ( new Error ( `Exited with ${ exitCode } ` ) ) ;
22+ } else if ( signal ) {
23+ reject ( new Error ( `Terminated by ${ signal } ` ) ) ;
24+ } else {
25+ const version : string = stdoutBuffer . join ( '' ) . trim ( ) ;
26+ terminal . writeLine ( `Found version "${ version } " for "${ packageName } "` ) ;
27+ resolve ( version ) ;
28+ }
29+ } ) ;
30+ } ) ;
31+ }
32+
1133export class BumpDecoupledLocalDependencies extends CommandLineAction {
1234 private readonly _terminal : ITerminal ;
1335
@@ -23,24 +45,24 @@ export class BumpDecoupledLocalDependencies extends CommandLineAction {
2345
2446 protected override async onExecuteAsync ( ) : Promise < void > {
2547 const terminal : ITerminal = this . _terminal ;
26- const rushConfiguration : RushConfiguration = RushConfiguration . loadFromDefaultLocation ( {
48+ const { projects , rushJsonFile } = RushConfiguration . loadFromDefaultLocation ( {
2749 startingFolder : process . cwd ( )
2850 } ) ;
2951
3052 const cyclicDependencyNames : Set < string > = new Set < string > ( ) ;
3153
32- for ( const project of rushConfiguration . projects ) {
33- for ( const cyclicDependencyProject of project . decoupledLocalDependencies ) {
34- cyclicDependencyNames . add ( cyclicDependencyProject ) ;
54+ for ( const { decoupledLocalDependencies } of projects ) {
55+ for ( const decoupledLocalDependency of decoupledLocalDependencies ) {
56+ cyclicDependencyNames . add ( decoupledLocalDependency ) ;
3557 }
3658 }
3759
38- const cyclicDependencyVersions : Map < string , string > = new Map < string , string > ( ) ;
60+ const decoupledLocalDependencyVersionsByName : Map < string , string > = new Map < string , string > ( ) ;
3961 await Async . forEachAsync (
4062 Array . from ( cyclicDependencyNames ) ,
41- async ( cyclicDependencyName ) => {
42- const version : string = await this . _getLatestPublishedVersionAsync ( terminal , cyclicDependencyName ) ;
43- cyclicDependencyVersions . set ( cyclicDependencyName , version ) ;
63+ async ( decoupledLocalDependencyName ) => {
64+ const version : string = await _getLatestPublishedVersionAsync ( terminal , decoupledLocalDependencyName ) ;
65+ decoupledLocalDependencyVersionsByName . set ( decoupledLocalDependencyName , version ) ;
4466 } ,
4567 {
4668 concurrency : 10
@@ -49,72 +71,52 @@ export class BumpDecoupledLocalDependencies extends CommandLineAction {
4971
5072 terminal . writeLine ( ) ;
5173
52- for ( const project of rushConfiguration . projects ) {
53- const commonVersions : CommonVersionsConfiguration = project . subspace . getCommonVersions ( ) ;
74+ for ( const {
75+ packageName,
76+ decoupledLocalDependencies,
77+ subspace,
78+ packageJson : { dependencies, devDependencies } ,
79+ packageJsonEditor
80+ } of projects ) {
81+ const { allowedAlternativeVersions } = subspace . getCommonVersions ( ) ;
5482
55- for ( const cyclicDependencyProject of project . decoupledLocalDependencies ) {
83+ for ( const cyclicDependencyProject of decoupledLocalDependencies ) {
5684 const existingVersion : string | undefined =
57- project . packageJson . dependencies ?. [ cyclicDependencyProject ] ??
58- project . packageJson . devDependencies ?. [ cyclicDependencyProject ] ;
85+ dependencies ?. [ cyclicDependencyProject ] ?? devDependencies ?. [ cyclicDependencyProject ] ;
5986 if (
6087 existingVersion &&
61- commonVersions . allowedAlternativeVersions . get ( cyclicDependencyProject ) ?. includes ( existingVersion )
88+ allowedAlternativeVersions . get ( cyclicDependencyProject ) ?. includes ( existingVersion )
6289 ) {
6390 // Skip if the existing version is allowed by common-versions.json
6491 continue ;
6592 }
6693
67- const newVersion : string = cyclicDependencyVersions . get ( cyclicDependencyProject ) ! ;
68- if ( project . packageJsonEditor . tryGetDependency ( cyclicDependencyProject ) ) {
69- project . packageJsonEditor . addOrUpdateDependency (
94+ const newVersion : string = decoupledLocalDependencyVersionsByName . get ( cyclicDependencyProject ) ! ;
95+ if ( packageJsonEditor . tryGetDependency ( cyclicDependencyProject ) ) {
96+ packageJsonEditor . addOrUpdateDependency (
7097 cyclicDependencyProject ,
7198 newVersion ,
7299 DependencyType . Regular
73100 ) ;
74101 }
75102
76- if ( project . packageJsonEditor . tryGetDevDependency ( cyclicDependencyProject ) ) {
77- project . packageJsonEditor . addOrUpdateDependency (
78- cyclicDependencyProject ,
79- newVersion ,
80- DependencyType . Dev
81- ) ;
103+ if ( packageJsonEditor . tryGetDevDependency ( cyclicDependencyProject ) ) {
104+ packageJsonEditor . addOrUpdateDependency ( cyclicDependencyProject , newVersion , DependencyType . Dev ) ;
82105 }
83106 }
84107
85- if ( project . packageJsonEditor . saveIfModified ( ) ) {
86- terminal . writeLine ( `Updated ${ project . packageName } ` ) ;
108+ if ( packageJsonEditor . saveIfModified ( ) ) {
109+ terminal . writeLine ( `Updated ${ packageName } ` ) ;
87110 }
88111 }
89112
90113 terminal . writeLine ( ) ;
91114
92115 // Update the Rush version in rush.json
93- const latestRushVersion : string = await this . _getLatestPublishedVersionAsync ( terminal , '@microsoft/rush' ) ;
94- const rushJson : { rushVersion : string } = await JsonFile . loadAsync ( rushConfiguration . rushJsonFile ) ;
116+ const latestRushVersion : string = await _getLatestPublishedVersionAsync ( terminal , '@microsoft/rush' ) ;
117+ const rushJson : IRushConfigurationJson = await JsonFile . loadAsync ( rushJsonFile ) ;
95118 rushJson . rushVersion = latestRushVersion ;
96- await JsonFile . saveAsync ( rushJson , rushConfiguration . rushJsonFile , { updateExistingFile : true } ) ;
97- terminal . writeLine ( `Updated ${ rushConfiguration . rushJsonFile } ` ) ;
98- }
99-
100- private async _getLatestPublishedVersionAsync ( terminal : ITerminal , packageName : string ) : Promise < string > {
101- return await new Promise ( ( resolve : ( result : string ) => void , reject : ( error : Error ) => void ) => {
102- const childProcess : ChildProcess = Executable . spawn ( 'npm' , [ 'view' , packageName , 'version' ] , {
103- stdio : [ 'ignore' , 'pipe' , 'pipe' ]
104- } ) ;
105- const stdoutBuffer : string [ ] = [ ] ;
106- childProcess . stdout ! . on ( 'data' , ( chunk ) => stdoutBuffer . push ( chunk ) ) ;
107- childProcess . on ( 'close' , ( exitCode : number | null , signal : NodeJS . Signals | null ) => {
108- if ( exitCode ) {
109- reject ( new Error ( `Exited with ${ exitCode } ` ) ) ;
110- } else if ( signal ) {
111- reject ( new Error ( `Terminated by ${ signal } ` ) ) ;
112- } else {
113- const version : string = stdoutBuffer . join ( '' ) . trim ( ) ;
114- terminal . writeLine ( `Found version "${ version } " for "${ packageName } "` ) ;
115- resolve ( version ) ;
116- }
117- } ) ;
118- } ) ;
119+ await JsonFile . saveAsync ( rushJson , rushJsonFile , { updateExistingFile : true } ) ;
120+ terminal . writeLine ( `Updated ${ rushJsonFile } ` ) ;
119121 }
120122}
0 commit comments