11import * as path from "path" ;
2+ import { BasePackageManager } from "./base-package-manager" ;
23import { exported , cache } from "./common/decorators" ;
34import { isInteractive } from "./common/helpers" ;
45import { CACACHE_DIRECTORY_NAME } from "./constants" ;
56
6- export class NodePackageManager implements INodePackageManager {
7+ export class NodePackageManager extends BasePackageManager implements INodePackageManager {
78 private static SCOPED_DEPENDENCY_REGEXP = / ^ ( @ .+ ?) (?: @ ( .+ ?) ) ? $ / ;
89 private static DEPENDENCY_REGEXP = / ^ ( .+ ?) (?: @ ( .+ ?) ) ? $ / ;
910
@@ -12,7 +13,9 @@ export class NodePackageManager implements INodePackageManager {
1213 private $errors : IErrors ,
1314 private $childProcess : IChildProcess ,
1415 private $logger : ILogger ,
15- private $httpClient : Server . IHttpClient ) { }
16+ private $httpClient : Server . IHttpClient ) {
17+ super ( 'npm' ) ;
18+ }
1619
1720 @exported ( "npm" )
1821 public async install ( packageName : string , pathToSave : string , config : INodePackageManagerInstallOptions ) : Promise < INpmInstallResultInfo > {
@@ -66,7 +69,7 @@ export class NodePackageManager implements INodePackageManager {
6669 // We cannot use the actual install with --json to get the information because of post-install scripts which may print on stdout
6770 // dry-run install is quite fast when the dependencies are already installed even for many dependencies (e.g. angular) so we can live with this approach
6871 // We need the --prefix here because without it no output is emitted on stdout because all the dependencies are already installed.
69- const spawnNpmDryRunResult = await this . $childProcess . spawnFromEvent ( this . getNpmExecutableName ( ) , params , "close" ) ;
72+ const spawnNpmDryRunResult = await this . $childProcess . spawnFromEvent ( this . getNpmExecutableName ( this . $hostInfo . isWindows ) , params , "close" ) ;
7073 return this . parseNpmInstallResult ( spawnNpmDryRunResult . stdout , spawnResult . stdout , packageName ) ;
7174 } catch ( err ) {
7275 if ( err . message && err . message . indexOf ( "EPEERINVALID" ) !== - 1 ) {
@@ -136,43 +139,12 @@ export class NodePackageManager implements INodePackageManager {
136139 return path . join ( cachePath . trim ( ) , CACACHE_DIRECTORY_NAME ) ;
137140 }
138141
139- private getNpmExecutableName ( ) : string {
140- let npmExecutableName = "npm" ;
141-
142- if ( this . $hostInfo . isWindows ) {
143- npmExecutableName += ".cmd" ;
144- }
145-
146- return npmExecutableName ;
147- }
148-
149- private getFlagsString ( config : any , asArray : boolean ) : any {
150- const array : Array < string > = [ ] ;
151- for ( const flag in config ) {
152- if ( flag === "global" ) {
153- array . push ( `--${ flag } ` ) ;
154- array . push ( `${ config [ flag ] } ` ) ;
155- } else if ( config [ flag ] ) {
156- if ( flag === "dist-tags" || flag === "versions" ) {
157- array . push ( ` ${ flag } ` ) ;
158- continue ;
159- }
160- array . push ( `--${ flag } ` ) ;
161- }
162- }
163- if ( asArray ) {
164- return array ;
165- }
166-
167- return array . join ( " " ) ;
168- }
169-
170142 private parseNpmInstallResult ( npmDryRunInstallOutput : string , npmInstallOutput : string , userSpecifiedPackageName : string ) : INpmInstallResultInfo {
171143 // TODO: Add tests for this functionality
172144 try {
173145 const originalOutput : INpmInstallCLIResult | INpm5InstallCliResult = JSON . parse ( npmDryRunInstallOutput ) ;
174- const npm5Output = < INpm5InstallCliResult > originalOutput ;
175- const npmOutput = < INpmInstallCLIResult > originalOutput ;
146+ const npm5Output = < INpm5InstallCliResult > originalOutput ;
147+ const npmOutput = < INpmInstallCLIResult > originalOutput ;
176148 let name : string ;
177149 _ . forOwn ( npmOutput . dependencies , ( peerDependency : INpmPeerDependencyInfo , key : string ) => {
178150 if ( ! peerDependency . required && ! peerDependency . peerMissing ) {
@@ -241,60 +213,17 @@ export class NodePackageManager implements INodePackageManager {
241213 }
242214
243215 private async getNpmInstallResult ( params : string [ ] , cwd : string ) : Promise < ISpawnResult > {
244- return new Promise < ISpawnResult > ( ( resolve , reject ) => {
245- const npmExecutable = this . getNpmExecutableName ( ) ;
216+ return new Promise < ISpawnResult > ( async ( resolve , reject ) => {
217+ const npmExecutable = this . getNpmExecutableName ( this . $hostInfo . isWindows ) ;
246218 const stdioValue = isInteractive ( ) ? "inherit" : "pipe" ;
247-
248219 const childProcess = this . $childProcess . spawn ( npmExecutable , params , { cwd, stdio : stdioValue } ) ;
249220
250- let isFulfilled = false ;
251- let capturedOut = "" ;
252- let capturedErr = "" ;
253-
254- if ( childProcess . stdout ) {
255- childProcess . stdout . on ( "data" , ( data : string ) => {
256- this . $logger . write ( data . toString ( ) ) ;
257- capturedOut += data ;
258- } ) ;
259- }
260-
261- if ( childProcess . stderr ) {
262- childProcess . stderr . on ( "data" , ( data : string ) => {
263- capturedErr += data ;
264- } ) ;
221+ try {
222+ const result = await this . processPackageManagerInstall ( childProcess , this . $hostInfo . isWindows , params ) ;
223+ resolve ( result ) ;
224+ } catch ( e ) {
225+ reject ( e ) ;
265226 }
266-
267- childProcess . on ( "close" , ( arg : any ) => {
268- const exitCode = typeof arg === "number" ? arg : arg && arg . code ;
269-
270- if ( exitCode === 0 ) {
271- isFulfilled = true ;
272- const result = {
273- stdout : capturedOut ,
274- stderr : capturedErr ,
275- exitCode
276- } ;
277-
278- resolve ( result ) ;
279- } else {
280- let errorMessage = `Command ${ npmExecutable } ${ params && params . join ( " " ) } failed with exit code ${ exitCode } ` ;
281- if ( capturedErr ) {
282- errorMessage += ` Error output: \n ${ capturedErr } ` ;
283- }
284-
285- if ( ! isFulfilled ) {
286- isFulfilled = true ;
287- reject ( new Error ( errorMessage ) ) ;
288- }
289- }
290- } ) ;
291-
292- childProcess . on ( "error" , ( err : Error ) => {
293- if ( ! isFulfilled ) {
294- isFulfilled = true ;
295- reject ( err ) ;
296- }
297- } ) ;
298227 } ) ;
299228 }
300229}
0 commit comments