diff --git a/lib/definitions/plugins.d.ts b/lib/definitions/plugins.d.ts index 2935878a59..06e5e4f7b6 100644 --- a/lib/definitions/plugins.d.ts +++ b/lib/definitions/plugins.d.ts @@ -5,6 +5,13 @@ interface IPluginsService { getAllInstalledPlugins(): IFuture; ensureAllDependenciesAreInstalled(): IFuture; afterPrepareAllPlugins(): IFuture; + /** + * Installs all devDependencies of the project. + * In case all of them are already installed, no operation will be executed. + * In case any of them is missing, all of them will be installed. + * @return {IFuture} + */ + installDevDependencies(): IFuture; } interface IPluginData extends INodeModuleData { @@ -53,6 +60,7 @@ interface IPluginVariablesService { * @return {IFuture} returns the changed plugin configuration file content. */ getPluginVariablePropertyName(pluginData: IPluginData): string; + } interface IPluginVariableData { diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index daf7447617..9ef7395a04 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -154,11 +154,20 @@ export class PlatformService implements IPlatformService { }).future()(); } - @helpers.hook('prepare') public preparePlatform(platform: string): IFuture { return (() => { this.validatePlatform(platform); + //Install dev-dependencies here, so before-prepare hooks will be executed correctly. + this.$pluginsService.installDevDependencies().wait(); + + this.preparePlatformCore(platform).wait(); + }).future()(); + } + + @helpers.hook('prepare') + private preparePlatformCore(platform: string): IFuture { + return (() => { platform = platform.toLowerCase(); this.ensurePlatformInstalled(platform).wait(); diff --git a/lib/services/plugins-service.ts b/lib/services/plugins-service.ts index ed85813b5b..4b497b6b51 100644 --- a/lib/services/plugins-service.ts +++ b/lib/services/plugins-service.ts @@ -185,6 +185,22 @@ export class PluginsService implements IPluginsService { return this.executeForAllInstalledPlatforms(action); } + public installDevDependencies(): IFuture { + return (() => { + let installedDependencies = this.$fs.exists(this.nodeModulesPath).wait() ? this.$fs.readDirectory(this.nodeModulesPath).wait() : []; + let packageJsonContent = this.$fs.readJson(this.getPackageJsonFilePath()).wait(); + let devDependencies = _.keys(packageJsonContent.devDependencies); + if(devDependencies.length && (this.$options.force || _.difference(devDependencies, installedDependencies).length)) { + let command = `npm install ${devDependencies.join(" ")}`; + if(this.$options.ignoreScripts) { + command += "--ignore-scripts"; + } + this.$logger.trace(`Command for installing devDependencies is: '${command}'.`); + this.$childProcess.exec(command, { cwd: this.$projectData.projectDir }).wait(); + } + }).future()(); + } + private get nodeModulesPath(): string { return path.join(this.$projectData.projectDir, "node_modules"); } diff --git a/test/platform-service.ts b/test/platform-service.ts index a4a766ecb5..2bf7b3c0b7 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -49,7 +49,8 @@ function createTestInjector() { }, ensureAllDependenciesAreInstalled: () => { return Future.fromResult(); - } + }, + installDevDependencies: () => Future.fromResult() }); testInjector.register("projectFilesManager", ProjectFilesManagerLib.ProjectFilesManager); testInjector.register("hooksService", stubs.HooksServiceStub);