From ade2236a9b4ca5a705f83f7de2bcb818a8ed2a9e Mon Sep 17 00:00:00 2001 From: Sumit Arora Date: Wed, 22 Feb 2017 17:19:29 -0500 Subject: [PATCH] feat(@angular/cli): adding the --app command option (#4754) --- .../@angular/cli/blueprints/class/index.ts | 11 +++++++- .../cli/blueprints/component/index.ts | 26 ++++++++++++------- .../cli/blueprints/directive/index.ts | 23 +++++++++------- .../@angular/cli/blueprints/enum/index.ts | 14 +++++++++- .../@angular/cli/blueprints/guard/index.ts | 7 +++-- .../cli/blueprints/interface/index.ts | 14 +++++++++- .../@angular/cli/blueprints/module/index.ts | 11 +++++++- .../@angular/cli/blueprints/pipe/index.ts | 16 +++++++++--- .../@angular/cli/blueprints/service/index.ts | 13 ++++++++-- packages/@angular/cli/commands/build.ts | 6 +++++ packages/@angular/cli/commands/eject.ts | 9 ++++++- packages/@angular/cli/commands/serve.ts | 2 +- packages/@angular/cli/commands/test.ts | 7 +++++ packages/@angular/cli/commands/xi18n.ts | 8 +++++- packages/@angular/cli/lib/config/schema.json | 4 +++ packages/@angular/cli/models/build-options.ts | 2 ++ .../@angular/cli/models/webpack-config.ts | 3 +-- .../cli/models/webpack-test-config.ts | 4 +-- .../cli/models/webpack-xi18n-config.ts | 9 ++++--- packages/@angular/cli/plugins/karma.ts | 6 +++-- packages/@angular/cli/tasks/build.ts | 15 +++++++---- packages/@angular/cli/tasks/eject.ts | 9 ++++--- packages/@angular/cli/tasks/extract-i18n.ts | 9 ++++--- packages/@angular/cli/tasks/serve.ts | 5 ++-- packages/@angular/cli/tasks/test.ts | 3 ++- packages/@angular/cli/utilities/app-utils.ts | 17 ++++++++++++ .../cli/utilities/dynamic-path-parser.js | 5 ++-- .../cli/utilities/find-parent-module.ts | 8 +++--- tests/acceptance/dynamic-path-parser.spec.js | 19 ++++++++------ 29 files changed, 213 insertions(+), 72 deletions(-) create mode 100644 packages/@angular/cli/utilities/app-utils.ts diff --git a/packages/@angular/cli/blueprints/class/index.ts b/packages/@angular/cli/blueprints/class/index.ts index 7086c4adae..a61702fa2f 100644 --- a/packages/@angular/cli/blueprints/class/index.ts +++ b/packages/@angular/cli/blueprints/class/index.ts @@ -1,3 +1,5 @@ +import {getAppFromConfig} from '../../utilities/app-utils'; + const stringUtils = require('ember-cli-string-utils'); const dynamicPathParser = require('../../utilities/dynamic-path-parser'); const Blueprint = require('../../ember-cli/lib/models/blueprint'); @@ -11,11 +13,18 @@ export default Blueprint.extend({ name: 'spec', type: Boolean, description: 'Specifies if a spec file is generated.' + }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' } ], normalizeEntityName: function (entityName: string) { - const parsedPath = dynamicPathParser(this.project, entityName.split('.')[0]); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, entityName.split('.')[0], appConfig); this.dynamicPath = parsedPath; return parsedPath.name; diff --git a/packages/@angular/cli/blueprints/component/index.ts b/packages/@angular/cli/blueprints/component/index.ts index 97e8e291f7..4d622ae7d3 100644 --- a/packages/@angular/cli/blueprints/component/index.ts +++ b/packages/@angular/cli/blueprints/component/index.ts @@ -1,4 +1,5 @@ import { NodeHost } from '../../lib/ast-tools'; +import {getAppFromConfig} from '../../utilities/app-utils'; import * as fs from 'fs'; import * as path from 'path'; @@ -71,14 +72,21 @@ export default Blueprint.extend({ type: Boolean, default: false, description: 'Specifies if declaring module exports the component.' + }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' } ], beforeInstall: function (options: any) { + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); if (options.module) { // Resolve path to module const modulePath = options.module.endsWith('.ts') ? options.module : `${options.module}.ts`; - const parsedPath = dynamicPathParser(this.project, modulePath); + const parsedPath = dynamicPathParser(this.project, modulePath, appConfig); this.pathToModule = path.join(this.project.root, parsedPath.dir, parsedPath.base); if (!fs.existsSync(this.pathToModule)) { @@ -86,7 +94,8 @@ export default Blueprint.extend({ } } else { try { - this.pathToModule = findParentModule(this.project, this.dynamicPath.dir); + this.pathToModule = findParentModule( + this.project.root, appConfig.root, this.dynamicPath.dir); } catch (e) { if (!options.skipImport) { throw `Error locating module for declaration\n\t${e}`; @@ -96,16 +105,12 @@ export default Blueprint.extend({ }, normalizeEntityName: function (entityName: string) { - const parsedPath = dynamicPathParser(this.project, entityName); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, entityName, appConfig); this.dynamicPath = parsedPath; - let defaultPrefix = ''; - if (this.project.ngConfig && - this.project.ngConfig.apps[0] && - this.project.ngConfig.apps[0].prefix) { - defaultPrefix = this.project.ngConfig.apps[0].prefix; - } + const defaultPrefix = (appConfig && appConfig.prefix) || ''; let prefix = (this.options.prefix === 'false' || this.options.prefix === '') ? '' : (this.options.prefix || defaultPrefix); @@ -191,7 +196,8 @@ export default Blueprint.extend({ if (!options.locals.flat) { dir += path.sep + options.dasherizedModuleName; } - const srcDir = this.project.ngConfig.apps[0].root; + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const srcDir = appConfig.root; this.appDir = dir.substr(dir.indexOf(srcDir) + srcDir.length); this.generatePath = dir; return dir; diff --git a/packages/@angular/cli/blueprints/directive/index.ts b/packages/@angular/cli/blueprints/directive/index.ts index f387e90027..fc68869d24 100644 --- a/packages/@angular/cli/blueprints/directive/index.ts +++ b/packages/@angular/cli/blueprints/directive/index.ts @@ -1,4 +1,5 @@ import {NodeHost} from '../../lib/ast-tools'; +import {getAppFromConfig} from '../../utilities/app-utils'; const path = require('path'); const fs = require('fs'); @@ -46,14 +47,21 @@ export default Blueprint.extend({ type: Boolean, default: false, description: 'Specifies if declaring module exports the component.' + }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' } ], beforeInstall: function(options: any) { + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); if (options.module) { // Resolve path to module const modulePath = options.module.endsWith('.ts') ? options.module : `${options.module}.ts`; - const parsedPath = dynamicPathParser(this.project, modulePath); + const parsedPath = dynamicPathParser(this.project, modulePath, appConfig); this.pathToModule = path.join(this.project.root, parsedPath.dir, parsedPath.base); if (!fs.existsSync(this.pathToModule)) { @@ -61,7 +69,8 @@ export default Blueprint.extend({ } } else { try { - this.pathToModule = findParentModule(this.project, this.dynamicPath.dir); + this.pathToModule = findParentModule + (this.project.root, appConfig.root, this.dynamicPath.dir); } catch (e) { if (!options.skipImport) { throw `Error locating module for declaration\n\t${e}`; @@ -71,16 +80,12 @@ export default Blueprint.extend({ }, normalizeEntityName: function (entityName: string) { - const parsedPath = dynamicPathParser(this.project, entityName); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, entityName, appConfig); this.dynamicPath = parsedPath; - let defaultPrefix = ''; - if (this.project.ngConfig && - this.project.ngConfig.apps[0] && - this.project.ngConfig.apps[0].prefix) { - defaultPrefix = this.project.ngConfig.apps[0].prefix; - } + const defaultPrefix = (appConfig && appConfig.prefix) || ''; let prefix = (this.options.prefix === 'false' || this.options.prefix === '') ? '' : (this.options.prefix || defaultPrefix); diff --git a/packages/@angular/cli/blueprints/enum/index.ts b/packages/@angular/cli/blueprints/enum/index.ts index 120b6737fa..e6875c9723 100644 --- a/packages/@angular/cli/blueprints/enum/index.ts +++ b/packages/@angular/cli/blueprints/enum/index.ts @@ -1,3 +1,5 @@ +import {getAppFromConfig} from '../../utilities/app-utils'; + const stringUtils = require('ember-cli-string-utils'); const dynamicPathParser = require('../../utilities/dynamic-path-parser'); const Blueprint = require('../../ember-cli/lib/models/blueprint'); @@ -5,8 +7,18 @@ const Blueprint = require('../../ember-cli/lib/models/blueprint'); export default Blueprint.extend({ description: '', + availableOptions: [ + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' + } + ], + normalizeEntityName: function (entityName: string) { - const parsedPath = dynamicPathParser(this.project, entityName); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, entityName, appConfig); this.dynamicPath = parsedPath; return parsedPath.name; diff --git a/packages/@angular/cli/blueprints/guard/index.ts b/packages/@angular/cli/blueprints/guard/index.ts index 19b75bd1b1..134babf78b 100644 --- a/packages/@angular/cli/blueprints/guard/index.ts +++ b/packages/@angular/cli/blueprints/guard/index.ts @@ -1,5 +1,6 @@ import {NodeHost} from '../../lib/ast-tools'; import { oneLine } from 'common-tags'; +import {getAppFromConfig} from '../../utilities/app-utils'; const path = require('path'); const fs = require('fs'); @@ -20,10 +21,11 @@ export default Blueprint.extend({ ], beforeInstall: function(options: any) { + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); if (options.module) { // Resolve path to module const modulePath = options.module.endsWith('.ts') ? options.module : `${options.module}.ts`; - const parsedPath = dynamicPathParser(this.project, modulePath); + const parsedPath = dynamicPathParser(this.project, modulePath, appConfig); this.pathToModule = path.join(this.project.root, parsedPath.dir, parsedPath.base); if (!fs.existsSync(this.pathToModule)) { @@ -33,7 +35,8 @@ export default Blueprint.extend({ }, normalizeEntityName: function (entityName: string) { - const parsedPath = dynamicPathParser(this.project, entityName); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, entityName, appConfig); this.dynamicPath = parsedPath; return parsedPath.name; diff --git a/packages/@angular/cli/blueprints/interface/index.ts b/packages/@angular/cli/blueprints/interface/index.ts index 2262dc19be..a0a49e0686 100644 --- a/packages/@angular/cli/blueprints/interface/index.ts +++ b/packages/@angular/cli/blueprints/interface/index.ts @@ -1,3 +1,5 @@ +import {getAppFromConfig} from '../../utilities/app-utils'; + const stringUtils = require('ember-cli-string-utils'); const dynamicPathParser = require('../../utilities/dynamic-path-parser'); const Blueprint = require('../../ember-cli/lib/models/blueprint'); @@ -9,8 +11,18 @@ export default Blueprint.extend({ '' ], + availableOptions: [ + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' + } + ], + normalizeEntityName: function (entityName: string) { - const parsedPath = dynamicPathParser(this.project, entityName); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, entityName, appConfig); this.dynamicPath = parsedPath; return parsedPath.name; diff --git a/packages/@angular/cli/blueprints/module/index.ts b/packages/@angular/cli/blueprints/module/index.ts index f23fa639d9..3586ee539f 100644 --- a/packages/@angular/cli/blueprints/module/index.ts +++ b/packages/@angular/cli/blueprints/module/index.ts @@ -1,3 +1,5 @@ +import {getAppFromConfig} from '../../utilities/app-utils'; + const path = require('path'); const Blueprint = require('../../ember-cli/lib/models/blueprint'); const dynamicPathParser = require('../../utilities/dynamic-path-parser'); @@ -22,12 +24,19 @@ export default Blueprint.extend({ type: Boolean, default: false, description: 'Specifies if a routing module file should be generated.' + }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' } ], normalizeEntityName: function (entityName: string) { this.entityName = entityName; - const parsedPath = dynamicPathParser(this.project, entityName); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, entityName, appConfig); this.dynamicPath = parsedPath; return parsedPath.name; diff --git a/packages/@angular/cli/blueprints/pipe/index.ts b/packages/@angular/cli/blueprints/pipe/index.ts index 95fc69f398..80e86197c4 100644 --- a/packages/@angular/cli/blueprints/pipe/index.ts +++ b/packages/@angular/cli/blueprints/pipe/index.ts @@ -1,4 +1,5 @@ import {NodeHost} from '../../lib/ast-tools'; +import {getAppFromConfig} from '../../utilities/app-utils'; const path = require('path'); const fs = require('fs'); @@ -41,14 +42,21 @@ export default Blueprint.extend({ type: Boolean, default: false, description: 'Specifies if declaring module exports the pipe.' + }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' } ], beforeInstall: function(options: any) { + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); if (options.module) { // Resolve path to module const modulePath = options.module.endsWith('.ts') ? options.module : `${options.module}.ts`; - const parsedPath = dynamicPathParser(this.project, modulePath); + const parsedPath = dynamicPathParser(this.project, modulePath, appConfig); this.pathToModule = path.join(this.project.root, parsedPath.dir, parsedPath.base); if (!fs.existsSync(this.pathToModule)) { @@ -56,7 +64,8 @@ export default Blueprint.extend({ } } else { try { - this.pathToModule = findParentModule(this.project, this.dynamicPath.dir); + this.pathToModule = findParentModule + (this.project.root, appConfig.root, this.dynamicPath.dir); } catch (e) { if (!options.skipImport) { throw `Error locating module for declaration\n\t${e}`; @@ -66,7 +75,8 @@ export default Blueprint.extend({ }, normalizeEntityName: function (entityName: string) { - const parsedPath = dynamicPathParser(this.project, entityName); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, entityName, appConfig); this.dynamicPath = parsedPath; return parsedPath.name; diff --git a/packages/@angular/cli/blueprints/service/index.ts b/packages/@angular/cli/blueprints/service/index.ts index 5cad35bd0b..fb14116901 100644 --- a/packages/@angular/cli/blueprints/service/index.ts +++ b/packages/@angular/cli/blueprints/service/index.ts @@ -1,5 +1,6 @@ import {NodeHost} from '../../lib/ast-tools'; import { oneLine } from 'common-tags'; +import {getAppFromConfig} from '../../utilities/app-utils'; const path = require('path'); const fs = require('fs'); @@ -28,6 +29,12 @@ export default Blueprint.extend({ name: 'module', type: String, aliases: ['m'], description: 'Allows specification of the declaring module.' + }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' } ], @@ -35,7 +42,8 @@ export default Blueprint.extend({ if (options.module) { // Resolve path to module const modulePath = options.module.endsWith('.ts') ? options.module : `${options.module}.ts`; - const parsedPath = dynamicPathParser(this.project, modulePath); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, modulePath, appConfig); this.pathToModule = path.join(this.project.root, parsedPath.dir, parsedPath.base); if (!fs.existsSync(this.pathToModule)) { @@ -45,7 +53,8 @@ export default Blueprint.extend({ }, normalizeEntityName: function (entityName: string) { - const parsedPath = dynamicPathParser(this.project, entityName); + const appConfig = getAppFromConfig(this.project.ngConfig.apps, this.options.app); + const parsedPath = dynamicPathParser(this.project, entityName, appConfig); this.dynamicPath = parsedPath; return parsedPath.name; diff --git a/packages/@angular/cli/commands/build.ts b/packages/@angular/cli/commands/build.ts index e32ca93466..a2e4b72e27 100644 --- a/packages/@angular/cli/commands/build.ts +++ b/packages/@angular/cli/commands/build.ts @@ -41,6 +41,12 @@ export const baseBuildCommandOptions: any = [ type: Number, default: pollDefault, description: 'enable and define the file watching poll time period (milliseconds)' + }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' } ]; diff --git a/packages/@angular/cli/commands/eject.ts b/packages/@angular/cli/commands/eject.ts index cfb05fd855..c681a96d84 100644 --- a/packages/@angular/cli/commands/eject.ts +++ b/packages/@angular/cli/commands/eject.ts @@ -6,11 +6,18 @@ const Command = require('../ember-cli/lib/models/command'); // defaults for BuildOptions export const baseEjectCommandOptions: any = [ ...baseBuildCommandOptions, - { name: 'force', 'type': Boolean } + { name: 'force', 'type': Boolean }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' + } ]; export interface EjectTaskOptions extends BuildOptions { force?: boolean; + app?: string; } diff --git a/packages/@angular/cli/commands/serve.ts b/packages/@angular/cli/commands/serve.ts index 41a8216af0..30ac169002 100644 --- a/packages/@angular/cli/commands/serve.ts +++ b/packages/@angular/cli/commands/serve.ts @@ -63,7 +63,7 @@ export const baseServeCommandOptions: any = overrideOptions( description: 'Enable hot module replacement', } ]), [ - { name: 'watch', default: true }, + { name: 'watch', default: true } ] ); diff --git a/packages/@angular/cli/commands/test.ts b/packages/@angular/cli/commands/test.ts index f76e294515..9beb3312c8 100644 --- a/packages/@angular/cli/commands/test.ts +++ b/packages/@angular/cli/commands/test.ts @@ -19,6 +19,7 @@ export interface TestOptions { progress?: boolean; config: string; poll?: number; + app?: string; } @@ -41,6 +42,12 @@ const TestCommand = EmberTestCommand.extend({ type: Number, default: pollDefault, description: 'enable and define the file watching poll time period (milliseconds)' + }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' } ], diff --git a/packages/@angular/cli/commands/xi18n.ts b/packages/@angular/cli/commands/xi18n.ts index 7a4e8b26a8..7bce94ca70 100644 --- a/packages/@angular/cli/commands/xi18n.ts +++ b/packages/@angular/cli/commands/xi18n.ts @@ -19,7 +19,13 @@ const Xi18nCommand = Command.extend({ }, { name: 'output-path', type: 'Path', default: null, aliases: ['op']}, { name: 'verbose', type: Boolean, default: false}, - { name: 'progress', type: Boolean, default: true } + { name: 'progress', type: Boolean, default: true }, + { + name: 'app', + type: String, + aliases: ['a'], + description: 'Specifies app name to use.' + } ], run: function (commandOptions: any) { diff --git a/packages/@angular/cli/lib/config/schema.json b/packages/@angular/cli/lib/config/schema.json index 647a77768b..529b4e0fb6 100644 --- a/packages/@angular/cli/lib/config/schema.json +++ b/packages/@angular/cli/lib/config/schema.json @@ -29,6 +29,10 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Name of the app." + }, "root": { "type": "string", "description": "The root directory of the app." diff --git a/packages/@angular/cli/models/build-options.ts b/packages/@angular/cli/models/build-options.ts index 919de64e2b..19b3f57c43 100644 --- a/packages/@angular/cli/models/build-options.ts +++ b/packages/@angular/cli/models/build-options.ts @@ -16,4 +16,6 @@ export interface BuildOptions { watch?: boolean; outputHashing?: string; poll?: number; + app?: string; + } diff --git a/packages/@angular/cli/models/webpack-config.ts b/packages/@angular/cli/models/webpack-config.ts index 4af56c7563..7d62e1954e 100644 --- a/packages/@angular/cli/models/webpack-config.ts +++ b/packages/@angular/cli/models/webpack-config.ts @@ -22,13 +22,12 @@ export interface WebpackConfigOptions { export class NgCliWebpackConfig { public config: any; public wco: WebpackConfigOptions; - constructor(buildOptions: BuildOptions) { + constructor(buildOptions: BuildOptions, appConfig: any) { this.validateBuildOptions(buildOptions); const configPath = CliConfig.configFilePath(); const projectRoot = path.dirname(configPath); - let appConfig = CliConfig.fromProject().config.apps[0]; appConfig = this.addAppConfigDefaults(appConfig); buildOptions = this.addTargetDefaults(buildOptions); diff --git a/packages/@angular/cli/models/webpack-test-config.ts b/packages/@angular/cli/models/webpack-test-config.ts index a2600fc22b..d7d3e81b7d 100644 --- a/packages/@angular/cli/models/webpack-test-config.ts +++ b/packages/@angular/cli/models/webpack-test-config.ts @@ -14,8 +14,8 @@ export interface WebpackTestOptions extends BuildOptions { codeCoverage?: boolean; } export class WebpackTestConfig extends NgCliWebpackConfig { - constructor(private testOptions: WebpackTestOptions) { - super(testOptions); + constructor(private testOptions: WebpackTestOptions, appConfig: any) { + super(testOptions, appConfig); } public buildConfig() { diff --git a/packages/@angular/cli/models/webpack-xi18n-config.ts b/packages/@angular/cli/models/webpack-xi18n-config.ts index d46ba6c3f4..667cbcee17 100644 --- a/packages/@angular/cli/models/webpack-xi18n-config.ts +++ b/packages/@angular/cli/models/webpack-xi18n-config.ts @@ -11,28 +11,29 @@ export interface XI18WebpackOptions { i18nFormat?: string; verbose?: boolean; progress?: boolean; + app?: string; } export class XI18nWebpackConfig extends NgCliWebpackConfig { public config: any; - constructor(public extractOptions: XI18WebpackOptions) { + constructor(public extractOptions: XI18WebpackOptions, public appConfig: any) { + super({ target: 'development', verbose: extractOptions.verbose, progress: extractOptions.progress - }); + }, appConfig); super.buildConfig(); } public buildConfig() { const configPath = CliConfig.configFilePath(); const projectRoot = path.dirname(configPath); - const appConfig = CliConfig.fromProject().config.apps[0]; const extractI18nConfig = getWebpackExtractI18nConfig(projectRoot, - appConfig, + this.appConfig, this.extractOptions.genDir, this.extractOptions.i18nFormat); diff --git a/packages/@angular/cli/plugins/karma.ts b/packages/@angular/cli/plugins/karma.ts index a7a155eade..97cd1a9bcb 100644 --- a/packages/@angular/cli/plugins/karma.ts +++ b/packages/@angular/cli/plugins/karma.ts @@ -6,6 +6,7 @@ import { Pattern } from './glob-copy-webpack-plugin'; import { extraEntryParser } from '../models/webpack-configs/utils'; import { WebpackTestConfig, WebpackTestOptions } from '../models/webpack-test-config'; +const getAppFromConfig = require('../utilities/app-utils').getAppFromConfig; function isDirectory(path: string) { try { @@ -16,7 +17,8 @@ function isDirectory(path: string) { } const init: any = (config: any) => { - const appConfig = CliConfig.fromProject().config.apps[0]; + const apps = CliConfig.fromProject().config.apps; + const appConfig = getAppFromConfig(apps, config.angularCli.app); const appRoot = path.join(config.basePath, appConfig.root); const testConfig: WebpackTestOptions = Object.assign({ environment: 'dev', @@ -66,7 +68,7 @@ const init: any = (config: any) => { } // Add webpack config. - const webpackConfig = new WebpackTestConfig(testConfig).buildConfig(); + const webpackConfig = new WebpackTestConfig(testConfig, appConfig).buildConfig(); const webpackMiddlewareConfig = { noInfo: true, // Hide webpack output because its noisy. stats: { // Also prevent chunk and module display output, cleaner look. Only emit errors. diff --git a/packages/@angular/cli/tasks/build.ts b/packages/@angular/cli/tasks/build.ts index b99d2986af..785be973ae 100644 --- a/packages/@angular/cli/tasks/build.ts +++ b/packages/@angular/cli/tasks/build.ts @@ -1,22 +1,27 @@ import * as rimraf from 'rimraf'; import * as path from 'path'; -const Task = require('../ember-cli/lib/models/task'); -const SilentError = require('silent-error'); import * as webpack from 'webpack'; + +import { getAppFromConfig } from '../utilities/app-utils'; import { BuildTaskOptions } from '../commands/build'; import { NgCliWebpackConfig } from '../models/webpack-config'; import { getWebpackStatsConfig } from '../models/webpack-configs/utils'; import { CliConfig } from '../models/config'; + const fs = require('fs'); +const Task = require('../ember-cli/lib/models/task'); +const SilentError = require('silent-error'); export default Task.extend({ run: function (runTaskOptions: BuildTaskOptions) { - const project = this.cliProject; const config = CliConfig.fromProject().config; - const outputPath = runTaskOptions.outputPath || config.apps[0].outDir; + const apps = CliConfig.fromProject().config.apps; + const app = getAppFromConfig(apps, runTaskOptions.app); + + const outputPath = runTaskOptions.outputPath || app.outDir; if (project.root === outputPath) { throw new SilentError('Output path MUST not be project root directory!'); } @@ -25,7 +30,7 @@ export default Task.extend({ } rimraf.sync(path.resolve(project.root, outputPath)); - const webpackConfig = new NgCliWebpackConfig(runTaskOptions).buildConfig(); + const webpackConfig = new NgCliWebpackConfig(runTaskOptions, app).buildConfig(); const webpackCompiler = webpack(webpackConfig); const statsConfig = getWebpackStatsConfig(runTaskOptions.verbose); diff --git a/packages/@angular/cli/tasks/eject.ts b/packages/@angular/cli/tasks/eject.ts index ab0057945e..06c6b99094 100644 --- a/packages/@angular/cli/tasks/eject.ts +++ b/packages/@angular/cli/tasks/eject.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import * as ts from 'typescript'; import * as webpack from 'webpack'; +import { getAppFromConfig } from '../utilities/app-utils'; import { EjectTaskOptions } from '../commands/eject'; import { NgCliWebpackConfig } from '../models/webpack-config'; import { CliConfig } from '../models/config'; @@ -400,15 +401,17 @@ export default Task.extend({ const project = this.cliProject; const cliConfig = CliConfig.fromProject(); const config = cliConfig.config; - const tsConfigPath = path.join(process.cwd(), config.apps[0].root, config.apps[0].tsconfig); - const outputPath = runTaskOptions.outputPath || config.apps[0].outDir; + const appConfig = getAppFromConfig(config.apps, runTaskOptions.app); + + const tsConfigPath = path.join(process.cwd(), appConfig.root, appConfig.tsconfig); + const outputPath = runTaskOptions.outputPath || appConfig.outDir; const force = runTaskOptions.force; if (project.root === outputPath) { throw new SilentError ('Output path MUST not be project root directory!'); } - const webpackConfig = new NgCliWebpackConfig(runTaskOptions).buildConfig(); + const webpackConfig = new NgCliWebpackConfig(runTaskOptions, appConfig).buildConfig(); const serializer = new JsonWebpackSerializer(process.cwd(), outputPath); const output = serializer.serialize(webpackConfig); const webpackConfigStr = `${serializer.generateVariables()}\n\nmodule.exports = ${output};\n`; diff --git a/packages/@angular/cli/tasks/extract-i18n.ts b/packages/@angular/cli/tasks/extract-i18n.ts index 5ec1df3d5b..fc1a4ee320 100644 --- a/packages/@angular/cli/tasks/extract-i18n.ts +++ b/packages/@angular/cli/tasks/extract-i18n.ts @@ -6,14 +6,14 @@ const Task = require('../ember-cli/lib/models/task'); import {XI18nWebpackConfig} from '../models/webpack-xi18n-config'; import {CliConfig} from '../models/config'; - +import {getAppFromConfig} from '../utilities/app-utils'; export const Extracti18nTask = Task.extend({ run: function (runTaskOptions: any) { const project = this.project; - const appConfig = CliConfig.fromProject().config.apps[0]; + const appConfig = getAppFromConfig(CliConfig.fromProject().config.apps, runTaskOptions.app); const buildDir = '.tmp'; const genDir = runTaskOptions.outputPath || appConfig.root; @@ -23,8 +23,9 @@ export const Extracti18nTask = Task.extend({ buildDir, i18nFormat: runTaskOptions.i18nFormat, verbose: runTaskOptions.verbose, - progress: runTaskOptions.progress - }).buildConfig(); + progress: runTaskOptions.progress, + app: runTaskOptions.app, + }, appConfig).buildConfig(); const webpackCompiler = webpack(config); diff --git a/packages/@angular/cli/tasks/serve.ts b/packages/@angular/cli/tasks/serve.ts index 4e40b018b0..af7b6d6f04 100644 --- a/packages/@angular/cli/tasks/serve.ts +++ b/packages/@angular/cli/tasks/serve.ts @@ -9,6 +9,7 @@ import { getWebpackStatsConfig } from '../models/webpack-configs/utils'; import { NgCliWebpackConfig } from '../models/webpack-config'; import { ServeTaskOptions } from '../commands/serve'; import { CliConfig } from '../models/config'; +import { getAppFromConfig } from '../utilities/app-utils'; const WebpackDevServer = require('webpack-dev-server'); const Task = require('../ember-cli/lib/models/task'); @@ -21,7 +22,7 @@ export default Task.extend({ let webpackCompiler: any; const projectConfig = CliConfig.fromProject().config; - const appConfig = projectConfig.apps[0]; + const appConfig = getAppFromConfig(projectConfig.apps, serveTaskOptions.app); const outputPath = serveTaskOptions.outputPath || appConfig.outDir; if (this.project.root === outputPath) { @@ -39,7 +40,7 @@ export default Task.extend({ serveTaskOptions = Object.assign({}, serveDefaults, serveTaskOptions); - let webpackConfig = new NgCliWebpackConfig(serveTaskOptions).buildConfig(); + let webpackConfig = new NgCliWebpackConfig(serveTaskOptions, appConfig).buildConfig(); const serverAddress = url.format({ protocol: serveTaskOptions.ssl ? 'https' : 'http', diff --git a/packages/@angular/cli/tasks/test.ts b/packages/@angular/cli/tasks/test.ts index 6d987cfb60..77fc191480 100644 --- a/packages/@angular/cli/tasks/test.ts +++ b/packages/@angular/cli/tasks/test.ts @@ -33,7 +33,8 @@ export default Task.extend({ codeCoverage: options.codeCoverage, sourcemap: options.sourcemap, progress: options.progress, - poll: options.poll + poll: options.poll, + app: options.app }; // Assign additional karmaConfig options to the local ngapp config diff --git a/packages/@angular/cli/utilities/app-utils.ts b/packages/@angular/cli/utilities/app-utils.ts new file mode 100644 index 0000000000..b3fc8f65db --- /dev/null +++ b/packages/@angular/cli/utilities/app-utils.ts @@ -0,0 +1,17 @@ +import {CliConfig as CliConfigInterface} from '../lib/config/schema'; + +export function getAppFromConfig(apps: CliConfigInterface['apps'], nameOrIndex: String) { + let app = apps[0]; + if (nameOrIndex) { + if (nameOrIndex.match(/^[0-9]+$/)) { + const index = parseInt(nameOrIndex.toString(), 10); + app = apps[index]; + } else { + const filtered = apps.filter((currentApp: any) => currentApp.name === nameOrIndex); + if (filtered.length > 0) { + app = filtered[0]; + } + } + } + return app; +} diff --git a/packages/@angular/cli/utilities/dynamic-path-parser.js b/packages/@angular/cli/utilities/dynamic-path-parser.js index e06fc27733..50e40e07c9 100644 --- a/packages/@angular/cli/utilities/dynamic-path-parser.js +++ b/packages/@angular/cli/utilities/dynamic-path-parser.js @@ -2,14 +2,13 @@ var path = require('path'); var process = require('process'); var fs = require('fs'); -module.exports = function dynamicPathParser(project, entityName) { +module.exports = function dynamicPathParser(project, entityName, appConfig) { var projectRoot = project.root; - var sourceDir = project.ngConfig.apps[0].root; + var sourceDir = appConfig.root; var appRoot = path.join(sourceDir, 'app'); var cwd = process.env.PWD; var rootPath = path.join(projectRoot, appRoot); - var outputPath = path.join(rootPath, entityName); if (entityName.indexOf(path.sep) === 0) { diff --git a/packages/@angular/cli/utilities/find-parent-module.ts b/packages/@angular/cli/utilities/find-parent-module.ts index 7a2273e190..3236167121 100644 --- a/packages/@angular/cli/utilities/find-parent-module.ts +++ b/packages/@angular/cli/utilities/find-parent-module.ts @@ -2,11 +2,13 @@ import * as fs from 'fs'; import * as path from 'path'; const SilentError = require('silent-error'); -export default function findParentModule(project: any, currentDir: string): string { - const sourceRoot = path.join(project.root, project.ngConfig.apps[0].root, 'app'); +export default function findParentModule( + projectRoot: string, appRoot: string, currentDir: string): string { + + const sourceRoot = path.join(projectRoot, appRoot, 'app'); // trim currentDir - currentDir = currentDir.replace(path.join(project.ngConfig.apps[0].root, 'app'), ''); + currentDir = currentDir.replace(path.join(appRoot, 'app'), ''); let pathToCheck = path.join(sourceRoot, currentDir); diff --git a/tests/acceptance/dynamic-path-parser.spec.js b/tests/acceptance/dynamic-path-parser.spec.js index 90058810d9..f9d1f30000 100644 --- a/tests/acceptance/dynamic-path-parser.spec.js +++ b/tests/acceptance/dynamic-path-parser.spec.js @@ -6,6 +6,9 @@ var dynamicPathParser = require('../../packages/@angular/cli/utilities/dynamic-p var mockFs = require('mock-fs'); var appDir = `src${path.sep}app`; +const appConfig = { + root: 'src' +}; describe('dynamic path parser', () => { var project; @@ -39,28 +42,28 @@ describe('dynamic path parser', () => { it('parse from proj root dir', () => { process.env.PWD = project.root; - var result = dynamicPathParser(project, entityName); + var result = dynamicPathParser(project, entityName, appConfig); expect(result.dir).to.equal(appDir); expect(result.name).to.equal(entityName); }); it('parse from proj src dir', () => { process.env.PWD = path.join(project.root, 'src'); - var result = dynamicPathParser(project, entityName); + var result = dynamicPathParser(project, entityName, appConfig); expect(result.dir).to.equal(appDir); expect(result.name).to.equal(entityName); }); it(`parse from proj src${path.sep}client dir`, () => { process.env.PWD = path.join(project.root, 'src', 'client'); - var result = dynamicPathParser(project, entityName); + var result = dynamicPathParser(project, entityName, appConfig); expect(result.dir).to.equal(appDir); expect(result.name).to.equal(entityName); }); it(`parse from proj src${path.sep}client${path.sep}app dir`, () => { process.env.PWD = path.join(project.root, 'src', 'client', 'app'); - var result = dynamicPathParser(project, entityName); + var result = dynamicPathParser(project, entityName, appConfig); expect(result.dir).to.equal(appDir); expect(result.name).to.equal(entityName); }); @@ -79,7 +82,7 @@ describe('dynamic path parser', () => { }; mockFs(mockFolder); process.env.PWD = path.join(project.root, 'src', 'app', 'child-dir'); - var result = dynamicPathParser(project, entityName); + var result = dynamicPathParser(project, entityName, appConfig); expect(result.dir).to.equal(`${appDir}${path.sep}child-dir`); expect(result.name).to.equal(entityName); }); @@ -97,7 +100,7 @@ describe('dynamic path parser', () => { }; mockFs(mockFolder); process.env.PWD = path.join(project.root, 'src', 'app', 'child-dir'); - var result = dynamicPathParser(project, '..' + path.sep + entityName); + var result = dynamicPathParser(project, '..' + path.sep + entityName, appConfig); expect(result.dir).to.equal(appDir); expect(result.name).to.equal(entityName); }); @@ -118,7 +121,7 @@ describe('dynamic path parser', () => { }; mockFs(mockFolder); process.env.PWD = path.join(project.root, 'src', 'app', 'child-dir', 'grand-child-dir'); - var result = dynamicPathParser(project, '..' + path.sep + entityName); + var result = dynamicPathParser(project, '..' + path.sep + entityName, appConfig); expect(result.dir).to.equal(`${appDir}${path.sep}child-dir`); expect(result.name).to.equal(entityName); }); @@ -134,7 +137,7 @@ describe('dynamic path parser', () => { }; mockFs(mockFolder); process.env.PWD = path.join(project.root, 'src', 'app', 'my-route'); - var result = dynamicPathParser(project, entityName); + var result = dynamicPathParser(project, entityName, appConfig); expect(result.dir).to.equal(`${appDir}${path.sep}+my-route`); expect(result.name).to.equal(entityName); });