Skip to content

Commit e2b051f

Browse files
Broccofilipesilva
authored andcommitted
feat(generate): add ability to specify module for import (angular#3811)
Closes angular#3806
1 parent ba477d3 commit e2b051f

File tree

15 files changed

+209
-26
lines changed

15 files changed

+209
-26
lines changed

packages/angular-cli/blueprints/component/index.js

+19-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const path = require('path');
2+
const fs = require('fs');
23
const chalk = require('chalk');
34
const Blueprint = require('../../ember-cli/lib/models/blueprint');
45
const dynamicPathParser = require('../../utilities/dynamic-path-parser');
@@ -19,15 +20,27 @@ module.exports = {
1920
{ name: 'spec', type: Boolean },
2021
{ name: 'view-encapsulation', type: String, aliases: ['ve'] },
2122
{ name: 'change-detection', type: String, aliases: ['cd'] },
22-
{ name: 'skip-import', type: Boolean, default: false }
23+
{ name: 'skip-import', type: Boolean, default: false },
24+
{ name: 'module', type: String, aliases: ['m'] }
2325
],
2426

2527
beforeInstall: function(options) {
26-
try {
27-
this.pathToModule = findParentModule(this.project, this.dynamicPath.dir);
28-
} catch(e) {
29-
if (!options.skipImport) {
30-
throw `Error locating module for declaration\n\t${e}`;
28+
if (options.module) {
29+
// Resolve path to module
30+
const modulePath = options.module.endsWith('.ts') ? options.module : `${options.module}.ts`;
31+
const parsedPath = dynamicPathParser(this.project, modulePath);
32+
this.pathToModule = path.join(this.project.root, parsedPath.dir, parsedPath.base);
33+
34+
if (!fs.existsSync(this.pathToModule)) {
35+
throw 'Module specified does not exist';
36+
}
37+
} else {
38+
try {
39+
this.pathToModule = findParentModule(this.project, this.dynamicPath.dir);
40+
} catch(e) {
41+
if (!options.skipImport) {
42+
throw `Error locating module for declaration\n\t${e}`;
43+
}
3144
}
3245
}
3346
},

packages/angular-cli/blueprints/directive/index.js

+19-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const path = require('path');
2+
const fs = require('fs');
23
const chalk = require('chalk');
34
const dynamicPathParser = require('../../utilities/dynamic-path-parser');
45
const stringUtils = require('ember-cli-string-utils');
@@ -15,15 +16,27 @@ module.exports = {
1516
{ name: 'flat', type: Boolean, default: true },
1617
{ name: 'prefix', type: String, default: null },
1718
{ name: 'spec', type: Boolean },
18-
{ name: 'skip-import', type: Boolean, default: false }
19+
{ name: 'skip-import', type: Boolean, default: false },
20+
{ name: 'module', type: String, aliases: ['m'] }
1921
],
2022

2123
beforeInstall: function(options) {
22-
try {
23-
this.pathToModule = findParentModule(this.project, this.dynamicPath.dir);
24-
} catch(e) {
25-
if (!options.skipImport) {
26-
throw `Error locating module for declaration\n\t${e}`;
24+
if (options.module) {
25+
// Resolve path to module
26+
const modulePath = options.module.endsWith('.ts') ? options.module : `${options.module}.ts`;
27+
const parsedPath = dynamicPathParser(this.project, modulePath);
28+
this.pathToModule = path.join(this.project.root, parsedPath.dir, parsedPath.base);
29+
30+
if (!fs.existsSync(this.pathToModule)) {
31+
throw ' ';
32+
}
33+
} else {
34+
try {
35+
this.pathToModule = findParentModule(this.project, this.dynamicPath.dir);
36+
} catch(e) {
37+
if (!options.skipImport) {
38+
throw `Error locating module for declaration\n\t${e}`;
39+
}
2740
}
2841
}
2942
},

packages/angular-cli/blueprints/pipe/index.js

+19-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const path = require('path');
2+
const fs = require('fs');
23
const chalk = require('chalk');
34
const dynamicPathParser = require('../../utilities/dynamic-path-parser');
45
const stringUtils = require('ember-cli-string-utils');
@@ -14,15 +15,27 @@ module.exports = {
1415
availableOptions: [
1516
{ name: 'flat', type: Boolean, default: true },
1617
{ name: 'spec', type: Boolean },
17-
{ name: 'skip-import', type: Boolean, default: false }
18+
{ name: 'skip-import', type: Boolean, default: false },
19+
{ name: 'module', type: String, aliases: ['m'] }
1820
],
1921

2022
beforeInstall: function(options) {
21-
try {
22-
this.pathToModule = findParentModule(this.project, this.dynamicPath.dir);
23-
} catch(e) {
24-
if (!options.skipImport) {
25-
throw `Error locating module for declaration\n\t${e}`;
23+
if (options.module) {
24+
// Resolve path to module
25+
const modulePath = options.module.endsWith('.ts') ? options.module : `${options.module}.ts`;
26+
const parsedPath = dynamicPathParser(this.project, modulePath);
27+
this.pathToModule = path.join(this.project.root, parsedPath.dir, parsedPath.base);
28+
29+
if (!fs.existsSync(this.pathToModule)) {
30+
throw 'Module specified does not exist';
31+
}
32+
} else {
33+
try {
34+
this.pathToModule = findParentModule(this.project, this.dynamicPath.dir);
35+
} catch(e) {
36+
if (!options.skipImport) {
37+
throw `Error locating module for declaration\n\t${e}`;
38+
}
2639
}
2740
}
2841
},

packages/angular-cli/blueprints/service/index.js

+39-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
11
const path = require('path');
2+
const fs = require('fs');
23
const chalk = require('chalk');
34
const dynamicPathParser = require('../../utilities/dynamic-path-parser');
45
const Blueprint = require('../../ember-cli/lib/models/blueprint');
6+
const NodeHost = require('@angular-cli/ast-tools').NodeHost;
7+
const stringUtils = require('ember-cli-string-utils');
8+
const astUtils = require('../../utilities/ast-utils');
59
const getFiles = Blueprint.prototype.files;
610

711
module.exports = {
812
description: '',
913

1014
availableOptions: [
1115
{ name: 'flat', type: Boolean, default: true },
12-
{ name: 'spec', type: Boolean }
16+
{ name: 'spec', type: Boolean },
17+
{ name: 'module', type: String, aliases: ['m'] }
1318
],
1419

20+
beforeInstall: function(options) {
21+
if (options.module) {
22+
// Resolve path to module
23+
const modulePath = options.module.endsWith('.ts') ? options.module : `${options.module}.ts`;
24+
const parsedPath = dynamicPathParser(this.project, modulePath);
25+
this.pathToModule = path.join(this.project.root, parsedPath.dir, parsedPath.base);
26+
27+
if (!fs.existsSync(this.pathToModule)) {
28+
throw 'Module specified does not exist';
29+
}
30+
}
31+
},
32+
1533
normalizeEntityName: function (entityName) {
1634
var parsedPath = dynamicPathParser(this.project, entityName);
1735

@@ -54,8 +72,25 @@ module.exports = {
5472
};
5573
},
5674

57-
afterInstall() {
58-
const warningMessage = 'Service is generated but not provided, it must be provided to be used';
59-
this._writeStatusToUI(chalk.yellow, 'WARNING', warningMessage);
75+
afterInstall(options) {
76+
const returns = [];
77+
78+
if (!this.pathToModule) {
79+
const warningMessage = 'Service is generated but not provided, it must be provided to be used';
80+
this._writeStatusToUI(chalk.yellow, 'WARNING', warningMessage);
81+
} else {
82+
const className = stringUtils.classify(`${options.entity.name}Service`);
83+
const fileName = stringUtils.dasherize(`${options.entity.name}.service`);
84+
const fullGeneratePath = path.join(this.project.root, this.generatePath);
85+
const moduleDir = path.parse(this.pathToModule).dir;
86+
const relativeDir = path.relative(moduleDir, fullGeneratePath);
87+
const importPath = relativeDir ? `./${relativeDir}/${fileName}` : `./${fileName}`;
88+
returns.push(
89+
astUtils.addProviderToModule(this.pathToModule, className, importPath)
90+
.then(change => change.apply(NodeHost)));
91+
this._writeStatusToUI(chalk.yellow, 'update', path.relative(this.project.root, this.pathToModule));
92+
}
93+
94+
return Promise.all(returns);
6095
}
6196
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import {ng} from '../../../utils/process';
2+
import {expectToFail} from '../../../utils/utils';
3+
4+
5+
export default function() {
6+
return Promise.resolve()
7+
.then(() => expectToFail(() =>
8+
ng('generate', 'component', 'test-component', '--module', 'app.moduleXXX.ts')));
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {join} from 'path';
2+
import {ng} from '../../../utils/process';
3+
import {expectFileToMatch} from '../../../utils/fs';
4+
5+
6+
export default function() {
7+
const modulePath = join('src', 'app', 'app.module.ts');
8+
9+
return ng('generate', 'component', 'test-component', '--module', 'app.module.ts')
10+
.then(() => expectFileToMatch(modulePath,
11+
/import { TestComponentComponent } from '.\/test-component\/test-component.component'/))
12+
13+
// Try to run the unit tests.
14+
.then(() => ng('build'));
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import {ng} from '../../../utils/process';
2+
import {join} from 'path';
3+
import {expectFileToExist} from '../../../utils/fs';
4+
5+
6+
export default function() {
7+
const directiveDir = join('src', 'app');
8+
return ng('generate', 'directive', 'test-directive')
9+
.then(() => expectFileToExist(join(directiveDir, 'test-directive.directive.ts')))
10+
.then(() => expectFileToExist(join(directiveDir, 'test-directive.directive.spec.ts')))
11+
12+
// Try to run the unit tests.
13+
.then(() => ng('test', '--single-run'));
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import {ng} from '../../../utils/process';
2+
import {expectToFail} from '../../../utils/utils';
3+
4+
export default function() {
5+
return Promise.resolve()
6+
.then(() => expectToFail(() =>
7+
ng('generate', 'directive', 'test-directive', '--module', 'app.moduleXXX.ts')));
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {join} from 'path';
2+
import {ng} from '../../../utils/process';
3+
import {expectFileToMatch} from '../../../utils/fs';
4+
5+
6+
export default function() {
7+
const modulePath = join('src', 'app', 'app.module.ts');
8+
9+
return ng('generate', 'directive', 'test-directive', '--module', 'app.module.ts')
10+
.then(() => expectFileToMatch(modulePath,
11+
/import { TestDirectiveDirective } from '.\/test-directive.directive'/))
12+
13+
// Try to run the unit tests.
14+
.then(() => ng('build'));
15+
}

tests/e2e/tests/generate/pipe.ts renamed to tests/e2e/tests/generate/pipe/pipe-basic.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {join} from 'path';
2-
import {ng} from '../../utils/process';
3-
import {expectFileToExist} from '../../utils/fs';
2+
import {ng} from '../../../utils/process';
43

4+
import {expectFileToExist} from '../../../utils/fs';
55

66
export default function() {
77
// Create the pipe in the same directory.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import {ng} from '../../../utils/process';
2+
import {expectToFail} from '../../../utils/utils';
3+
4+
5+
export default function() {
6+
return Promise.resolve()
7+
.then(() => expectToFail(() =>
8+
ng('generate', 'pipe', 'test-pipe', '--module', 'app.moduleXXX.ts')));
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {join} from 'path';
2+
import {ng} from '../../../utils/process';
3+
import {expectFileToMatch} from '../../../utils/fs';
4+
5+
6+
export default function() {
7+
const modulePath = join('src', 'app', 'app.module.ts');
8+
9+
return ng('generate', 'pipe', 'test-pipe', '--module', 'app.module.ts')
10+
.then(() => expectFileToMatch(modulePath,
11+
/import { TestPipePipe } from '.\/test-pipe.pipe'/))
12+
13+
// Try to run the unit tests.
14+
.then(() => ng('build'));
15+
}

tests/e2e/tests/generate/service.ts renamed to tests/e2e/tests/generate/service/service-basic.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {join} from 'path';
2-
import {ng} from '../../utils/process';
3-
import {expectFileToExist} from '../../utils/fs';
2+
import {ng} from '../../../utils/process';
3+
import {expectFileToExist} from '../../../utils/fs';
44

55

66
export default function() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import {ng} from '../../../utils/process';
2+
import {expectToFail} from '../../../utils/utils';
3+
4+
5+
export default function() {
6+
return Promise.resolve()
7+
.then(() => expectToFail(() =>
8+
ng('generate', 'service', 'test-service', '--module', 'app.moduleXXX.ts')));
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {join} from 'path';
2+
import {ng} from '../../../utils/process';
3+
import {expectFileToMatch} from '../../../utils/fs';
4+
5+
6+
export default function() {
7+
const modulePath = join('src', 'app', 'app.module.ts');
8+
9+
return ng('generate', 'service', 'test-service', '--module', 'app.module.ts')
10+
.then(() => expectFileToMatch(modulePath,
11+
/import { TestServiceService } from '.\/test-service.service'/))
12+
13+
// Try to run the unit tests.
14+
.then(() => ng('build'));
15+
}

0 commit comments

Comments
 (0)