1- import { exec } from "child_process" ;
1+ import { spawn } from "child_process" ;
22import * as path from "path" ;
33import { TemplateManager } from "../../cli/lib/TemplateManager" ;
44import { Config , FS_TOKEN , IFileSystem , ProjectTemplate } from "../types" ;
@@ -149,10 +149,10 @@ export class PackageManager {
149149
150150 public static addPackage ( packageName : string , verbose : boolean = false ) : boolean {
151151 const managerCommand = this . getManager ( ) ;
152- const command = this . getInstallCommand ( managerCommand , packageName ) ;
152+ const args = this . getInstallArgs ( packageName ) ;
153153 try {
154154 // tslint:disable-next-line:object-literal-sort-keys
155- Util . execSync ( command , { stdio : "pipe" , encoding : "utf8" } ) ;
155+ Util . spawnSync ( managerCommand , args , { stdio : "pipe" , encoding : "utf8" } ) ;
156156 } catch ( error ) {
157157 Util . log ( `Error installing package ${ packageName } with ${ managerCommand } ` ) ;
158158 if ( verbose ) {
@@ -165,7 +165,7 @@ export class PackageManager {
165165 }
166166
167167 public static async queuePackage ( packageName : string , verbose = false ) {
168- const command = this . getInstallCommand ( this . getManager ( ) , packageName ) . replace ( " --save" , " --no-save" ) ;
168+ const args = this . getInstallArgs ( packageName ) . map ( arg => arg === ' --save' ? ' --no-save' : arg ) ;
169169 const [ packName , version ] = packageName . split ( / @ (? = [ ^ \/ ] + $ ) / ) ;
170170 const packageJSON = this . getPackageJSON ( ) ;
171171 if ( ! packageJSON . dependencies ) {
@@ -190,13 +190,24 @@ export class PackageManager {
190190 // D.P. Concurrent install runs should be supported
191191 // https://github.com/npm/npm/issues/5948
192192 // https://github.com/npm/npm/issues/2500
193+ const managerCommand = this . getManager ( ) ;
193194 const task = new Promise < { packageName , error , stdout , stderr } > ( ( resolve , reject ) => {
194- const child = exec (
195- command , { } ,
196- ( error , stdout , stderr ) => {
197- resolve ( { packageName, error, stdout, stderr } ) ;
198- }
199- ) ;
195+ const child = spawn ( managerCommand , args ) ;
196+ let stdout = '' ;
197+ let stderr = '' ;
198+ child . stdout ?. on ( 'data' , ( data ) => {
199+ stdout += data . toString ( ) ;
200+ } ) ;
201+ child . stderr ?. on ( 'data' , ( data ) => {
202+ stderr += data . toString ( ) ;
203+ } ) ;
204+ child . on ( 'close' , ( code ) => {
205+ const error = code !== 0 ? new Error ( `Process exited with code ${ code } ` ) : null ;
206+ resolve ( { packageName, error, stdout, stderr } ) ;
207+ } ) ;
208+ child . on ( 'error' , ( err ) => {
209+ resolve ( { packageName, error : err , stdout, stderr } ) ;
210+ } ) ;
200211 } ) ;
201212 task [ "packageName" ] = packName ;
202213 this . installQueue . push ( task ) ;
@@ -281,6 +292,10 @@ export class PackageManager {
281292 }
282293 }
283294
295+ private static getInstallArgs ( packageName : string ) : string [ ] {
296+ return [ 'install' , packageName , '--quiet' , '--save' ] ;
297+ }
298+
284299 private static getManager ( /*config:Config*/ ) : string {
285300 //stub to potentially swap out managers
286301 return "npm" ;
0 commit comments