diff --git a/docs/documentation/generate/module.md b/docs/documentation/generate/module.md
index 24a4fe95a3af..55559f122406 100644
--- a/docs/documentation/generate/module.md
+++ b/docs/documentation/generate/module.md
@@ -26,6 +26,16 @@
+
+ module
+
+ --module
(aliases: -m
)
+
+
+ Specifies where the module should be imported.
+
+
+
spec
@@ -45,3 +55,5 @@
Specifies if a routing module file should be generated.
+
+
diff --git a/packages/@angular/cli/blueprints/module/index.ts b/packages/@angular/cli/blueprints/module/index.ts
index 91fcd7a5c608..e954f6b34073 100644
--- a/packages/@angular/cli/blueprints/module/index.ts
+++ b/packages/@angular/cli/blueprints/module/index.ts
@@ -1,9 +1,15 @@
-import {CliConfig} from '../../models/config';
-import {getAppFromConfig} from '../../utilities/app-utils';
-import {dynamicPathParser} from '../../utilities/dynamic-path-parser';
+import * as chalk from 'chalk';
+import * as path from 'path';
+import { oneLine } from 'common-tags';
+import { NodeHost } from '../../lib/ast-tools';
+import { CliConfig } from '../../models/config';
+import { getAppFromConfig } from '../../utilities/app-utils';
+import { resolveModulePath } from '../../utilities/resolve-module-file';
+import { dynamicPathParser } from '../../utilities/dynamic-path-parser';
-const path = require('path');
-const Blueprint = require('../../ember-cli/lib/models/blueprint');
+const stringUtils = require('ember-cli-string-utils');
+const Blueprint = require('../../ember-cli/lib/models/blueprint');
+const astUtils = require('../../utilities/ast-utils');
const getFiles = Blueprint.prototype.files;
export default Blueprint.extend({
@@ -32,9 +38,22 @@ export default Blueprint.extend({
type: String,
aliases: ['a'],
description: 'Specifies app name to use.'
+ },
+ {
+ name: 'module',
+ type: String, aliases: ['m'],
+ description: 'Specifies where the module should be imported.'
}
],
+ beforeInstall: function(options: any) {
+ if (options.module) {
+ const appConfig = getAppFromConfig(this.options.app);
+ this.pathToModule =
+ resolveModulePath(options.module, this.project, this.project.root, appConfig);
+ }
+ },
+
normalizeEntityName: function (entityName: string) {
this.entityName = entityName;
const appConfig = getAppFromConfig(this.options.app);
@@ -59,7 +78,7 @@ export default Blueprint.extend({
};
},
- files: function() {
+ files: function () {
let fileList = getFiles.call(this) as Array;
if (!this.options || !this.options.spec) {
@@ -84,5 +103,36 @@ export default Blueprint.extend({
return this.generatePath;
}
};
+ },
+
+ afterInstall(options: any) {
+ const returns: Array = [];
+
+ if (!this.pathToModule) {
+ const warningMessage = oneLine`
+ Module is generated but not provided,
+ it must be provided to be used
+ `;
+ this._writeStatusToUI(chalk.yellow, 'WARNING', warningMessage);
+ } else {
+ let className = stringUtils.classify(`${options.entity.name}Module`);
+ let fileName = stringUtils.dasherize(`${options.entity.name}.module`);
+ if (options.routing) {
+ className = stringUtils.classify(`${options.entity.name}RoutingModule`);
+ fileName = stringUtils.dasherize(`${options.entity.name}-routing.module`);
+ }
+ const fullGeneratePath = path.join(this.project.root, this.generatePath);
+ const moduleDir = path.parse(this.pathToModule).dir;
+ const relativeDir = path.relative(moduleDir, fullGeneratePath);
+ const importPath = relativeDir ? `./${relativeDir}/${fileName}` : `./${fileName}`;
+ returns.push(
+ astUtils.addImportToModule(this.pathToModule, className, importPath)
+ .then((change: any) => change.apply(NodeHost)));
+ this._writeStatusToUI(chalk.yellow,
+ 'update',
+ path.relative(this.project.root, this.pathToModule));
+ }
+
+ return Promise.all(returns);
}
});
diff --git a/packages/@angular/cli/utilities/ast-utils.ts b/packages/@angular/cli/utilities/ast-utils.ts
index 0369f46df36e..0d0a07fca32f 100644
--- a/packages/@angular/cli/utilities/ast-utils.ts
+++ b/packages/@angular/cli/utilities/ast-utils.ts
@@ -9,5 +9,6 @@ export {
getDecoratorMetadata,
addDeclarationToModule,
addProviderToModule,
+ addImportToModule,
addExportToModule
} from '../lib/ast-tools';
diff --git a/tests/e2e/tests/generate/module/module-import.ts b/tests/e2e/tests/generate/module/module-import.ts
new file mode 100644
index 000000000000..2f2f2104fe9c
--- /dev/null
+++ b/tests/e2e/tests/generate/module/module-import.ts
@@ -0,0 +1,43 @@
+import { join } from 'path';
+import { ng } from '../../../utils/process';
+import { expectFileToMatch } from '../../../utils/fs';
+
+export default function () {
+ const modulePath = join('src', 'app', 'app.module.ts');
+ const subModulePath = join('src', 'app', 'sub', 'sub.module.ts');
+ const deepSubModulePath = join('src', 'app', 'sub', 'deep', 'deep.module.ts');
+
+ return Promise.resolve()
+ .then(() => ng('generate', 'module', 'sub'))
+ .then(() => ng('generate', 'module', 'sub/deep'))
+
+ .then(() => ng('generate', 'module', 'test1', '--module', 'app.module.ts'))
+ .then(() => expectFileToMatch(modulePath,
+ /import { Test1Module } from '.\/test1\/test1.module'/))
+ .then(() => expectFileToMatch(modulePath, /imports: \[(.|\s)*Test1Module(.|\s)*\]/m))
+
+ .then(() => ng('generate', 'module', 'test2', '--module', 'app.module'))
+ .then(() => expectFileToMatch(modulePath,
+ /import { Test2Module } from '.\/test2\/test2.module'/))
+ .then(() => expectFileToMatch(modulePath, /imports: \[(.|\s)*Test2Module(.|\s)*\]/m))
+
+ .then(() => ng('generate', 'module', 'test3', '--module', 'app'))
+ .then(() => expectFileToMatch(modulePath,
+ /import { Test3Module } from '.\/test3\/test3.module'/))
+ .then(() => expectFileToMatch(modulePath, /imports: \[(.|\s)*Test3Module(.|\s)*\]/m))
+
+ .then(() => ng('generate', 'module', 'test4', '--routing', '--module', 'app'))
+ .then(() => expectFileToMatch(modulePath,
+ /import { Test4RoutingModule } from '.\/test4\/test4-routing.module'/))
+ .then(() => expectFileToMatch(modulePath, /imports: \[(.|\s)*Test4RoutingModule(.|\s)*\]/m))
+
+ .then(() => ng('generate', 'module', 'test5', '--module', 'sub'))
+ .then(() => expectFileToMatch(subModulePath,
+ /import { Test5Module } from '.\/..\/test5\/test5.module'/))
+ .then(() => expectFileToMatch(subModulePath, /imports: \[(.|\s)*Test5Module(.|\s)*\]/m))
+
+ .then(() => ng('generate', 'module', 'test6', '--module', join('sub', 'deep'))
+ .then(() => expectFileToMatch(deepSubModulePath,
+ /import { Test6Module } from '.\/..\/..\/test6\/test6.module'/))
+ .then(() => expectFileToMatch(deepSubModulePath, /imports: \[(.|\s)*Test6Module(.|\s)*\]/m)));
+}