88
99import { UnsuccessfulWorkflowExecution } from '@angular-devkit/schematics' ;
1010import { NodeWorkflow } from '@angular-devkit/schematics/tools' ;
11- import { execSync } from 'child_process' ;
12- import { existsSync , promises as fsPromises } from 'fs' ;
11+ import { execSync , spawnSync } from 'child_process' ;
12+ import { existsSync , promises as fs } from 'fs' ;
1313import npa from 'npm-package-arg' ;
1414import pickManifest from 'npm-pick-manifest' ;
1515import * as path from 'path' ;
16- import { join } from 'path' ;
16+ import { join , resolve } from 'path' ;
1717import * as semver from 'semver' ;
1818import { Argv } from 'yargs' ;
1919import { PackageManager } from '../../../lib/config/workspace-schema' ;
@@ -27,9 +27,7 @@ import { SchematicEngineHost } from '../../command-builder/utilities/schematic-e
2727import { subscribeToWorkflow } from '../../command-builder/utilities/schematic-workflow' ;
2828import { colors } from '../../utilities/color' ;
2929import { disableVersionCheck } from '../../utilities/environment-options' ;
30- import { installAllPackages , runTempPackageBin } from '../../utilities/install-package' ;
3130import { writeErrorToLogFile } from '../../utilities/log-file' ;
32- import { ensureCompatibleNpm } from '../../utilities/package-manager' ;
3331import {
3432 PackageIdentifier ,
3533 PackageManifest ,
@@ -167,7 +165,7 @@ export class UpdateCommandModule extends CommandModule<UpdateCommandArgs> {
167165 async run ( options : Options < UpdateCommandArgs > ) : Promise < number | void > {
168166 const { logger, packageManager } = this . context ;
169167
170- await ensureCompatibleNpm ( this . context . root ) ;
168+ packageManager . ensureCompatibility ( ) ;
171169
172170 // Check if the current installed CLI version is older than the latest compatible version.
173171 if ( ! disableVersionCheck ) {
@@ -183,11 +181,7 @@ export class UpdateCommandModule extends CommandModule<UpdateCommandArgs> {
183181 `Installing a temporary Angular CLI versioned ${ cliVersionToInstall } to perform the update.` ,
184182 ) ;
185183
186- return runTempPackageBin (
187- `@angular/cli@${ cliVersionToInstall } ` ,
188- packageManager ,
189- process . argv . slice ( 2 ) ,
190- ) ;
184+ return this . runTempBinary ( `@angular/cli@${ cliVersionToInstall } ` , process . argv . slice ( 2 ) ) ;
191185 }
192186 }
193187
@@ -233,7 +227,7 @@ export class UpdateCommandModule extends CommandModule<UpdateCommandArgs> {
233227 logger . info ( `Found ${ rootDependencies . size } dependencies.` ) ;
234228
235229 const workflow = new NodeWorkflow ( this . context . root , {
236- packageManager : this . context . packageManager ,
230+ packageManager : packageManager . name ,
237231 packageManagerForce : options . force ,
238232 // __dirname -> favor @schematics/update from this package
239233 // Otherwise, use packages from the active workspace (migrations)
@@ -252,7 +246,7 @@ export class UpdateCommandModule extends CommandModule<UpdateCommandArgs> {
252246 force : options . force ,
253247 next : options . next ,
254248 verbose : options . verbose ,
255- packageManager,
249+ packageManager : packageManager . name ,
256250 packages : [ ] ,
257251 } ,
258252 ) ;
@@ -681,28 +675,27 @@ export class UpdateCommandModule extends CommandModule<UpdateCommandArgs> {
681675 verbose : options . verbose ,
682676 force : options . force ,
683677 next : options . next ,
684- packageManager : this . context . packageManager ,
678+ packageManager : this . context . packageManager . name ,
685679 packages : packagesToUpdate ,
686680 } ,
687681 ) ;
688682
689683 if ( success ) {
690684 try {
691- await fsPromises . rm ( path . join ( this . context . root , 'node_modules' ) , {
685+ await fs . rm ( path . join ( this . context . root , 'node_modules' ) , {
692686 force : true ,
693687 recursive : true ,
694688 maxRetries : 3 ,
695689 } ) ;
696690 } catch { }
697691
698- const result = await installAllPackages (
699- this . context . packageManager ,
692+ const installationSuccess = await this . context . packageManager . installAll (
700693 options . force ? [ '--force' ] : [ ] ,
701694 this . context . root ,
702695 ) ;
703696
704- if ( result !== 0 ) {
705- return result ;
697+ if ( ! installationSuccess ) {
698+ return 1 ;
706699 }
707700 }
708701
@@ -891,7 +884,7 @@ export class UpdateCommandModule extends CommandModule<UpdateCommandArgs> {
891884 this . context . logger ,
892885 {
893886 verbose,
894- usingYarn : this . context . packageManager === PackageManager . Yarn ,
887+ usingYarn : this . context . packageManager . name === PackageManager . Yarn ,
895888 } ,
896889 ) ;
897890
@@ -928,6 +921,52 @@ export class UpdateCommandModule extends CommandModule<UpdateCommandArgs> {
928921 // We end up using Angular ClI v13 to run the migrations if we run the migrations using the CLI installed major version + 1 logic.
929922 return VERSION . major ;
930923 }
924+
925+ private async runTempBinary ( packageName : string , args : string [ ] = [ ] ) : Promise < number > {
926+ const { success, tempNodeModules } = await this . context . packageManager . installTemp ( packageName ) ;
927+ if ( ! success ) {
928+ return 1 ;
929+ }
930+
931+ // Remove version/tag etc... from package name
932+ // Ex: @angular /cli@latest -> @angular/cli
933+ const packageNameNoVersion = packageName . substring ( 0 , packageName . lastIndexOf ( '@' ) ) ;
934+ const pkgLocation = join ( tempNodeModules , packageNameNoVersion ) ;
935+ const packageJsonPath = join ( pkgLocation , 'package.json' ) ;
936+
937+ // Get a binary location for this package
938+ let binPath : string | undefined ;
939+ if ( existsSync ( packageJsonPath ) ) {
940+ const content = await fs . readFile ( packageJsonPath , 'utf-8' ) ;
941+ if ( content ) {
942+ const { bin = { } } = JSON . parse ( content ) ;
943+ const binKeys = Object . keys ( bin ) ;
944+
945+ if ( binKeys . length ) {
946+ binPath = resolve ( pkgLocation , bin [ binKeys [ 0 ] ] ) ;
947+ }
948+ }
949+ }
950+
951+ if ( ! binPath ) {
952+ throw new Error ( `Cannot locate bin for temporary package: ${ packageNameNoVersion } .` ) ;
953+ }
954+
955+ const { status, error } = spawnSync ( process . execPath , [ binPath , ...args ] , {
956+ stdio : 'inherit' ,
957+ env : {
958+ ...process . env ,
959+ NG_DISABLE_VERSION_CHECK : 'true' ,
960+ NG_CLI_ANALYTICS : 'false' ,
961+ } ,
962+ } ) ;
963+
964+ if ( status === null && error ) {
965+ throw error ;
966+ }
967+
968+ return status ?? 0 ;
969+ }
931970}
932971
933972/**
0 commit comments