@@ -23,11 +23,15 @@ export class PluginsService implements IPluginsService {
2323
2424 public add ( plugin : string ) : IFuture < void > {
2525 return ( ( ) => {
26+ let dependencies = this . getAllInstalledModules ( ) . wait ( ) ;
2627 let pluginName = this . executeNpmCommand ( PluginsService . INSTALL_COMMAND_NAME , plugin ) . wait ( ) ;
27- let nodeModuleData = this . getNodeModuleData ( pluginName ) ;
28- if ( ! nodeModuleData . isPlugin ) {
28+ let nodeModuleData = this . getNodeModuleData ( pluginName ) . wait ( ) ;
29+ if ( nodeModuleData && ! nodeModuleData . isPlugin ) {
2930 // We should remove already downloaded plugin and show an error message
30- this . executeNpmCommand ( PluginsService . UNINSTALL_COMMAND_NAME , pluginName ) . wait ( ) ;
31+ let pluginNameLowerCase = pluginName . toLowerCase ( ) ;
32+ if ( ! _ . any ( dependencies , dependency => dependency . name . toLowerCase ( ) === pluginNameLowerCase ) ) {
33+ this . executeNpmCommand ( PluginsService . UNINSTALL_COMMAND_NAME , pluginName ) . wait ( ) ;
34+ }
3135 this . $errors . failWithoutHelp ( `${ plugin } is not a valid NativeScript plugin. Verify that the plugin package.json file contains a nativescript key and try again.` ) ;
3236 }
3337
@@ -93,21 +97,27 @@ export class PluginsService implements IPluginsService {
9397 } ) . future < void > ( ) ( ) ;
9498 }
9599
100+ public ensureAllDependenciesAreInstalled ( ) : IFuture < void > {
101+ return this . $childProcess . exec ( "npm install " ) ;
102+ }
103+
96104 public getAllInstalledPlugins ( ) : IFuture < IPluginData [ ] > {
97105 return ( ( ) => {
98- let nodeModules = this . $fs . readDirectory ( this . nodeModulesPath ) . wait ( ) ;
99- let plugins : IPluginData [ ] = [ ] ;
100- _ . each ( nodeModules , nodeModuleName => {
101- let nodeModuleData = this . getNodeModuleData ( nodeModuleName ) ;
102- if ( nodeModuleData . isPlugin ) {
103- plugins . push ( this . convertToPluginData ( nodeModuleData ) ) ;
104- }
105- } ) ;
106-
107- return plugins ;
106+ let nodeModules = this . getAllInstalledModules ( ) . wait ( ) ;
107+ return _ . filter ( nodeModules , nodeModuleData => nodeModuleData && nodeModuleData . isPlugin ) ;
108108 } ) . future < IPluginData [ ] > ( ) ( ) ;
109109 }
110110
111+ private getAllInstalledModules ( ) : IFuture < INodeModuleData [ ] > {
112+ return ( ( ) => {
113+ this . ensureAllDependenciesAreInstalled ( ) . wait ( ) ;
114+ this . $fs . ensureDirectoryExists ( this . nodeModulesPath ) . wait ( ) ;
115+
116+ let nodeModules = this . $fs . readDirectory ( this . nodeModulesPath ) . wait ( ) ;
117+ return _ . map ( nodeModules , nodeModuleName => this . getNodeModuleData ( nodeModuleName ) . wait ( ) ) ;
118+ } ) . future < INodeModuleData [ ] > ( ) ( ) ;
119+ }
120+
111121 private executeNpmCommand ( npmCommandName : string , npmCommandArguments : string ) : IFuture < string > {
112122 return ( ( ) => {
113123 let command = this . composeNpmCommand ( npmCommandName , npmCommandArguments ) ;
@@ -117,7 +127,7 @@ export class PluginsService implements IPluginsService {
117127 }
118128
119129 private composeNpmCommand ( npmCommandName : string , npmCommandArguments : string ) : string {
120- let command = ` npm ${ npmCommandName } ${ npmCommandArguments } --save ` ;
130+ let command = ` npm ${ npmCommandName } " ${ npmCommandArguments } " --save ` ;
121131 if ( this . $options . production ) {
122132 command += " --production " ;
123133 }
@@ -141,19 +151,23 @@ export class PluginsService implements IPluginsService {
141151 } ) ;
142152 }
143153
144- private getNodeModuleData ( moduleName : string ) : INodeModuleData {
145- let fullNodeModulePath = path . join ( this . nodeModulesPath , moduleName ) ;
146- let packageJsonFilePath = path . join ( fullNodeModulePath , "package.json" ) ;
147- let data = require ( packageJsonFilePath ) ;
148- let result = {
149- name : data . name ,
150- version : data . version ,
151- fullPath : fullNodeModulePath ,
152- isPlugin : data . nativescript !== undefined ,
153- moduleInfo : data . nativescript
154- } ;
155-
156- return result ;
154+ private getNodeModuleData ( moduleName : string ) : IFuture < INodeModuleData > {
155+ return ( ( ) => {
156+ let fullNodeModulePath = path . join ( this . nodeModulesPath , moduleName ) ;
157+ let packageJsonFilePath = path . join ( fullNodeModulePath , "package.json" ) ;
158+ if ( this . $fs . exists ( packageJsonFilePath ) . wait ( ) ) {
159+ let data = require ( packageJsonFilePath ) ;
160+ return {
161+ name : data . name ,
162+ version : data . version ,
163+ fullPath : fullNodeModulePath ,
164+ isPlugin : data . nativescript !== undefined ,
165+ moduleInfo : data . nativescript
166+ } ;
167+ }
168+
169+ return null ;
170+ } ) . future < INodeModuleData > ( ) ( ) ;
157171 }
158172
159173 private convertToPluginData ( nodeModuleData : INodeModuleData ) : IPluginData {
@@ -178,7 +192,7 @@ export class PluginsService implements IPluginsService {
178192 return frameworkData . version ;
179193 } ) . future < string > ( ) ( ) ;
180194 }
181-
195+
182196 private mergeXml ( xml1 : string , xml2 : string ) : IFuture < string > {
183197 let future = new Future < string > ( ) ;
184198
0 commit comments