Skip to content

Commit e32fd1c

Browse files
feat(blueprints): adding generation of routing config
1 parent 6830cef commit e32fd1c

File tree

8 files changed

+270
-18
lines changed

8 files changed

+270
-18
lines changed

README.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,37 @@ with two sub-routes. The file structure will be as follows:
118118
| | |-- hero.service.ts
119119
| |-- ...
120120
|-- app.ts
121+
|-- route-config.ts
121122
...
122123
```
123124

124-
Afterwards to use the new route open your main app component, import
125-
`hero-root.component.ts` and add it in the route config:
125+
By default the cli will add the import statements for HeroList and HeroDetail to
126+
`hero-root.component.ts`:
126127

127128
```
128129
@RouteConfig([
129-
{path:'/hero/...', name: 'HeroRoot', component: HeroRoot}
130+
{path:'/', name: 'HeroList', component: HeroListComponent, useAsDefault: true},
131+
{path:'/:id', name: 'HeroDetail', component: HeroDetailComponent}
130132
])
131133
```
132134

135+
The generated `route-config.ts` file is also updated with the following:
136+
137+
```
138+
// DO NOT EDIT THIS FILE
139+
// IT IS AUTO GENERATED BY ANGULAR-CLI
140+
import {HeroRoot} from './hero/hero-root.component';
141+
142+
export const CliRouteConfig = [
143+
{path:'/hero/...', name: 'HeroRoot', component: HeroRoot}
144+
];
145+
```
146+
133147
Visiting `http://localhost:4200/hero` will show the hero list.
134148

135149

150+
There is an optional flag for `skip-router-generation` which will not add the route to the `CliRouteConfig` for the application.
151+
136152
### Creating a build
137153

138154
```bash
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"routes": []
3+
}

addon/ng2/blueprints/ng2/files/src/app/__name__.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Component} from 'angular2/core';
22
import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from 'angular2/router';
3-
3+
import {CliRouteConfig} from './route-config';
44

55
@Component({
66
selector: '<%= htmlComponentName %>-app',
@@ -11,7 +11,8 @@ import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from 'angular2/router'
1111
})
1212
@RouteConfig([
1313

14-
])
14+
].concat(CliRouteConfig))
15+
1516
export class <%= jsComponentName %>App {
1617
defaultMeaning: number = 42;
1718

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
// DO NOT EDIT THIS FILE
3+
// IT IS AUTO GENERATED BY ANGULAR-CLI
4+
5+
export const CliRouteConfig = [
6+
7+
];
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// DO NOT EDIT THIS FILE
2+
// IT IS AUTO GENERATED BY ANGULAR-CLI
3+
<%= imports %>
4+
5+
export const CliRouteConfig = [
6+
<%= routeDefinitions %>
7+
];
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
var fs = require('fs-extra');
2+
var path = require('path');
3+
4+
var imports, routeDefinitions;
5+
6+
module.exports = {
7+
description: 'Registers the route with the router.',
8+
9+
locals: function (options) {
10+
return generateLocals.call(this, options);
11+
},
12+
13+
beforeInstall: function (options) {
14+
var routeConfigPath = path.join(options.project.root, 'src', 'app', 'route-config.ts');
15+
try {
16+
fs.unlinkSync(routeConfigPath);
17+
} catch (e) {
18+
}
19+
}
20+
};
21+
22+
function generateLocals(options) {
23+
var ngCliConfigPath = path.join(options.project.root, 'angular-cli.json');
24+
var ngCliConfig = JSON.parse(fs.readFileSync(ngCliConfigPath, 'utf-8'));
25+
26+
imports = ngCliConfig.routes.map(route =>
27+
`import {${route.component}} from '${route.componentPath}';`)
28+
.join('\n');
29+
30+
routeDefinitions = ngCliConfig.routes.map(route =>
31+
`{path: '${route.routePath}', name: '${route.component}', component: ${route.component}},`
32+
)
33+
.join('\n');
34+
35+
return {
36+
imports,
37+
routeDefinitions
38+
}
39+
}

addon/ng2/blueprints/route/index.js

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,71 @@
1-
var stringUtils = require('ember-cli/lib/utilities/string');
1+
var fs = require('fs-extra');
2+
var path = require('path');
3+
var chalk = require('chalk');
24

35
module.exports = {
4-
description: ''
5-
6-
//locals: function(options) {
7-
// // Return custom template variables here.
8-
// return {
9-
//
10-
// };
11-
//}
12-
13-
// afterInstall: function(options) {
14-
// // Perform extra work here.
15-
// }
6+
description: 'Generates a route and a template.',
7+
8+
availableOptions: [{
9+
name: 'skip-router-generation',
10+
type: Boolean,
11+
default: false,
12+
aliases: ['srg']
13+
}, {
14+
name: 'default',
15+
type: Boolean,
16+
default: false
17+
}],
18+
19+
beforeInstall: function (options, locals) {
20+
if (!options.skipRouterGeneration) {
21+
updateRouteConfig.call(this, 'add', options, locals);
22+
}
23+
},
24+
25+
afterInstall: function (options, locals) {
26+
if (!options.skipRouterGeneration) {
27+
return this.lookupBlueprint('route-config')
28+
.install(options);
29+
}
30+
},
31+
32+
beforeUninstall: function (options, locals) {
33+
updateRouteConfig.call(this, 'remove', options, locals);
34+
},
35+
36+
afterUninstall: function (options, locals) {
37+
return this.lookupBlueprint('route-config')
38+
.install(options);
39+
}
1640
};
41+
42+
function updateRouteConfig(action, options, locals) {
43+
var entity = options.entity;
44+
var actionColorMap = {
45+
add: 'green',
46+
remove: 'red'
47+
};
48+
var color = actionColorMap[action] || 'gray';
49+
50+
this._writeStatusToUI(chalk[color], action + ' route', entity.name);
51+
52+
var ngCliConfigPath = path.join(options.project.root, 'angular-cli.json');
53+
54+
// TODO use default option
55+
var route = {
56+
routePath: `/${locals.dasherizedModuleName}/...`,
57+
component: `${locals.classifiedModuleName}Root`,
58+
componentPath: `./${locals.dasherizedModuleName}/${locals.dasherizedModuleName}-root.component`
59+
};
60+
61+
var ngCliConfig = JSON.parse(fs.readFileSync(ngCliConfigPath, 'utf-8'));
62+
if (action === 'add' && ngCliConfig.routes.findIndex(el => el.routePath === route.routePath) === -1) {
63+
ngCliConfig.routes.push(route)
64+
} else if (action === 'remove') {
65+
var idx = ngCliConfig.routes.findIndex(el => el.routePath === route.routePath);
66+
if (idx > -1) {
67+
ngCliConfig.routes.splice(idx, 1);
68+
}
69+
}
70+
fs.writeFileSync(ngCliConfigPath, JSON.stringify(ngCliConfig, null, 2));
71+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
'use strict';
2+
3+
var fs = require('fs-extra');
4+
var ng = require('../helpers/ng');
5+
var existsSync = require('exists-sync');
6+
var expect = require('chai').expect;
7+
var forEach = require('lodash/forEach');
8+
var path = require('path');
9+
var tmp = require('../helpers/tmp');
10+
var root = process.cwd();
11+
var util = require('util');
12+
var conf = require('ember-cli/tests/helpers/conf');
13+
var testPath = path.join(root, 'tmp', 'foo', 'src', 'app', 'my-route');
14+
var appPath = path.join(root, 'tmp', 'foo', 'src', 'app');
15+
var routeRegex = /name: 'MyRouteRoot'/g;
16+
var route = {
17+
routePath: `/my-route/...`,
18+
component: `MyRouteRoot`,
19+
componentPath: `./my-route/my-route-root.component`
20+
};
21+
22+
var fileExpectations = function (expectation) {
23+
expect(existsSync(path.join(testPath, 'my-route.service.spec.ts'))).to.equal(expectation);
24+
expect(existsSync(path.join(testPath, 'my-route.service.ts'))).to.equal(expectation);
25+
expect(existsSync(path.join(testPath, 'my-route-list.component.ts'))).to.equal(expectation);
26+
expect(existsSync(path.join(testPath, 'my-route-list.component.spec.ts'))).to.equal(expectation);
27+
expect(existsSync(path.join(testPath, 'my-route-list.component.html'))).to.equal(expectation);
28+
expect(existsSync(path.join(testPath, 'my-route-list.component.css'))).to.equal(expectation);
29+
expect(existsSync(path.join(testPath, 'my-route-detail.component.ts'))).to.equal(expectation);
30+
expect(existsSync(path.join(testPath, 'my-route-detail.component.spec.ts'))).to.equal(expectation);
31+
expect(existsSync(path.join(testPath, 'my-route-detail.component.html'))).to.equal(expectation);
32+
expect(existsSync(path.join(testPath, 'my-route-detail.component.css'))).to.equal(expectation);
33+
expect(existsSync(path.join(testPath, 'my-route-root.component.ts'))).to.equal(expectation);
34+
};
35+
36+
describe('Acceptance: ng generate route', function () {
37+
before(conf.setup);
38+
39+
after(conf.restore);
40+
41+
beforeEach(function () {
42+
return tmp.setup('./tmp')
43+
.then(function () {
44+
process.chdir('./tmp');
45+
})
46+
.then(function () {
47+
return ng([
48+
'new',
49+
'foo',
50+
'--skip-npm',
51+
'--skip-bower'
52+
]);
53+
});
54+
});
55+
56+
afterEach(function () {
57+
this.timeout(10000);
58+
59+
return tmp.teardown('./tmp');
60+
});
61+
62+
it('ng generate route my-route', function () {
63+
return ng([
64+
'generate',
65+
'route',
66+
'my-route'
67+
])
68+
.then(_ => {
69+
var ngCliConfig = JSON.parse(fs.readFileSync(path.join(root, 'tmp', 'foo', 'angular-cli.json'), 'utf-8'));
70+
var routeConfigString = fs.readFileSync(path.join(appPath, 'route-config.ts'), 'utf-8').toString();
71+
expect(routeConfigString.match(routeRegex).length).to.equal(1);
72+
73+
fileExpectations(true);
74+
75+
expect(ngCliConfig.routes[0]).to.deep.equal(route);
76+
});
77+
});
78+
it('ng generate route my-route with skip-router-generation flag does not generate router config', function () {
79+
return ng([
80+
'generate',
81+
'route',
82+
'my-route',
83+
'--skip-router-generation'
84+
])
85+
.then(_ => {
86+
var ngCliConfig = JSON.parse(fs.readFileSync(path.join(root, 'tmp', 'foo', 'angular-cli.json'), 'utf-8'));
87+
88+
fileExpectations(true);
89+
90+
expect(ngCliConfig.routes.length).to.equal(0);
91+
});
92+
});
93+
it('ng generate route my-route then destroy', function () {
94+
return ng([
95+
'generate',
96+
'route',
97+
'my-route'
98+
])
99+
.then(() => {
100+
var ngCliConfig = JSON.parse(fs.readFileSync(path.join(root, 'tmp', 'foo', 'angular-cli.json'), 'utf-8'));
101+
var routeConfigString = fs.readFileSync(path.join(appPath, 'route-config.ts'), 'utf-8').toString();
102+
expect(routeConfigString.match(routeRegex).length).to.equal(1);
103+
104+
fileExpectations(true);
105+
106+
expect(ngCliConfig.routes.length).to.equal(1);
107+
expect(ngCliConfig.routes[0]).to.deep.equal(route);
108+
}).then(() => {
109+
return ng([
110+
'destroy',
111+
'route',
112+
'my-route'
113+
]).then(() => {
114+
var ngCliConfig = JSON.parse(fs.readFileSync(path.join(root, 'tmp', 'foo', 'angular-cli.json'), 'utf-8'));
115+
var routeConfigString = fs.readFileSync(path.join(appPath, 'route-config.ts'), 'utf-8').toString();
116+
expect(routeConfigString.match(routeRegex)).to.equal(null);
117+
118+
fileExpectations(false);
119+
120+
expect(ngCliConfig.routes.length).to.equal(0);
121+
})
122+
});
123+
});
124+
});

0 commit comments

Comments
 (0)