Skip to content

Commit 83eba07

Browse files
committed
feat(@angular/cli): Update generate & new to use schematics
This feature is related to #6593
1 parent cb0cc08 commit 83eba07

File tree

16 files changed

+1473
-272
lines changed

16 files changed

+1473
-272
lines changed

package-lock.json

+821-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@
4040
},
4141
"homepage": "https://github.com/angular/angular-cli",
4242
"dependencies": {
43-
"@angular-devkit/build-optimizer": "0.0.10",
43+
"@angular-devkit/build-optimizer": "0.0.11",
44+
"@angular-devkit/schematics": "0.0.13",
45+
"@schematics/angular": "0.0.15",
4446
"autoprefixer": "^6.5.3",
4547
"chalk": "^2.0.1",
4648
"circular-dependency-plugin": "^3.0.0",
+108-96
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
1-
import * as chalk from 'chalk';
2-
import * as fs from 'fs';
3-
import * as os from 'os';
4-
import * as path from 'path';
1+
import { cyan, yellow } from 'chalk';
2+
const stringUtils = require('ember-cli-string-utils');
53
import { oneLine } from 'common-tags';
64
import { CliConfig } from '../models/config';
75

6+
import 'rxjs/add/observable/of';
7+
import 'rxjs/add/operator/ignoreElements';
8+
import {
9+
getCollection,
10+
getEngineHost
11+
} from '../utilities/schematics';
12+
import { DynamicPathOptions, dynamicPathParser } from '../utilities/dynamic-path-parser';
13+
import { getAppFromConfig } from '../utilities/app-utils';
14+
import * as path from 'path';
15+
import { SchematicAvailableOptions } from '../tasks/schematic-get-options';
16+
817
const Command = require('../ember-cli/lib/models/command');
9-
const Blueprint = require('../ember-cli/lib/models/blueprint');
10-
const parseOptions = require('../ember-cli/lib/utilities/parse-options');
1118
const SilentError = require('silent-error');
1219

13-
function loadBlueprints(): Array<any> {
14-
const blueprintList = fs.readdirSync(path.join(__dirname, '..', 'blueprints'));
15-
const blueprints = blueprintList
16-
.filter(bp => bp.indexOf('-test') === -1)
17-
.filter(bp => bp !== 'ng')
18-
.map(bp => Blueprint.load(path.join(__dirname, '..', 'blueprints', bp)));
19-
20-
return blueprints;
21-
}
2220

2321
export default Command.extend({
2422
name: 'generate',
25-
description: 'Generates and/or modifies files based on a blueprint.',
23+
description: 'Generates and/or modifies files based on a schematic.',
2624
aliases: ['g'],
2725

2826
availableOptions: [
@@ -34,117 +32,131 @@ export default Command.extend({
3432
description: 'Run through without making any changes.'
3533
},
3634
{
37-
name: 'lint-fix',
35+
name: 'force',
3836
type: Boolean,
39-
aliases: ['lf'],
40-
description: 'Use lint to fix files after generation.'
37+
default: false,
38+
aliases: ['f'],
39+
description: 'Forces overwriting of files.'
40+
},
41+
{
42+
name: 'app',
43+
type: String,
44+
aliases: ['a'],
45+
description: 'Specifies app name to use.'
46+
},
47+
{
48+
name: 'collection',
49+
type: String,
50+
aliases: ['c'],
51+
description: 'Schematics collection to use.'
4152
},
4253
{
43-
name: 'verbose',
54+
name: 'lint-fix',
4455
type: Boolean,
45-
default: false,
46-
aliases: ['v'],
47-
description: 'Adds more details to output logging.'
56+
aliases: ['lf'],
57+
description: 'Use lint to fix files after generation.'
4858
}
4959
],
5060

5161
anonymousOptions: [
52-
'<blueprint>'
62+
'<schematic>'
5363
],
5464

55-
beforeRun: function (rawArgs: string[]) {
56-
if (!rawArgs.length) {
57-
return;
65+
getCollectionName(rawArgs: string[]) {
66+
let collectionName = CliConfig.getValue('defaults.schematics.collection')
67+
if (rawArgs) {
68+
const parsedArgs = this.parseArgs(rawArgs, false);
69+
if (parsedArgs.options.collection) {
70+
collectionName = parsedArgs.options.collection;
71+
}
5872
}
73+
return collectionName;
74+
},
75+
76+
beforeRun: function(rawArgs: string[]) {
5977

6078
const isHelp = ['--help', '-h'].includes(rawArgs[0]);
6179
if (isHelp) {
6280
return;
6381
}
6482

65-
this.blueprints = loadBlueprints();
66-
67-
const name = rawArgs[0];
68-
const blueprint = this.blueprints.find((bp: any) => bp.name === name
69-
|| (bp.aliases && bp.aliases.includes(name)));
70-
71-
if (!blueprint) {
72-
SilentError.debugOrThrow('@angular/cli/commands/generate',
73-
`Invalid blueprint: ${name}`);
74-
}
75-
76-
if (!rawArgs[1]) {
77-
SilentError.debugOrThrow('@angular/cli/commands/generate',
78-
`The \`ng generate ${name}\` command requires a name to be specified.`);
83+
const schematicName = rawArgs[0];
84+
if (!schematicName) {
85+
return Promise.reject(new SilentError(oneLine`
86+
The "ng generate" command requires a
87+
schematic name to be specified.
88+
For more details, use "ng help".
89+
`));
7990
}
8091

8192
if (/^\d/.test(rawArgs[1])) {
8293
SilentError.debugOrThrow('@angular/cli/commands/generate',
83-
`The \`ng generate ${name} ${rawArgs[1]}\` file name cannot begin with a digit.`);
94+
`The \`ng generate ${schematicName} ${rawArgs[1]}\` file name cannot begin with a digit.`);
8495
}
8596

86-
rawArgs[0] = blueprint.name;
87-
this.registerOptions(blueprint);
88-
},
97+
const SchematicGetOptionsTask = require('../tasks/schematic-get-options').default;
8998

90-
printDetailedHelp: function () {
91-
if (!this.blueprints) {
92-
this.blueprints = loadBlueprints();
93-
}
94-
this.ui.writeLine(chalk.cyan(' Available blueprints'));
95-
this.ui.writeLine(this.blueprints.map((bp: any) => bp.printBasicHelp(false)).join(os.EOL));
99+
const getOptionsTask = new SchematicGetOptionsTask({
100+
ui: this.ui,
101+
project: this.project
102+
});
103+
104+
return getOptionsTask.run({
105+
schematicName,
106+
collectionName: this.getCollectionName(rawArgs)
107+
})
108+
.then((availableOptions: SchematicAvailableOptions) => {
109+
this.registerOptions({
110+
availableOptions: availableOptions
111+
});
112+
});
96113
},
97114

98115
run: function (commandOptions: any, rawArgs: string[]) {
99-
const name = rawArgs[0];
100-
if (!name) {
101-
return Promise.reject(new SilentError(oneLine`
102-
The "ng generate" command requires a
103-
blueprint name to be specified.
104-
For more details, use "ng help".
105-
`));
116+
if (rawArgs[0] === 'module' && !rawArgs[1]) {
117+
throw 'The `ng generate module` command requires a name to be specified.';
106118
}
107119

108-
const blueprint = this.blueprints.find((bp: any) => bp.name === name
109-
|| (bp.aliases && bp.aliases.includes(name)));
110-
111-
const projectName = CliConfig.getValue('project.name');
112-
const blueprintOptions = {
113-
target: this.project.root,
114-
entity: {
115-
name: rawArgs[1],
116-
options: parseOptions(rawArgs.slice(2))
117-
},
118-
projectName,
119-
ui: this.ui,
120+
const entityName = rawArgs[1];
121+
commandOptions.name = stringUtils.dasherize(entityName.split(path.sep).pop());
122+
123+
const appConfig = getAppFromConfig(commandOptions.app);
124+
const dynamicPathOptions: DynamicPathOptions = {
120125
project: this.project,
121-
settings: this.settings,
122-
testing: this.testing,
123-
args: rawArgs,
124-
...commandOptions
126+
entityName: entityName,
127+
appConfig: appConfig,
128+
dryRun: commandOptions.dryRun
125129
};
130+
const parsedPath = dynamicPathParser(dynamicPathOptions);
131+
commandOptions.sourceDir = appConfig.root;
132+
commandOptions.path = parsedPath.dir.replace(appConfig.root + path.sep, '');
126133

127-
return blueprint.install(blueprintOptions)
128-
.then(() => {
129-
const lintFix = commandOptions.lintFix !== undefined ?
130-
commandOptions.lintFix : CliConfig.getValue('defaults.lintFix');
131-
132-
if (lintFix && blueprint.modifiedFiles) {
133-
const LintTask = require('../tasks/lint').default;
134-
const lintTask = new LintTask({
135-
ui: this.ui,
136-
project: this.project
137-
});
138-
139-
return lintTask.run({
140-
fix: true,
141-
force: true,
142-
silent: true,
143-
configs: [{
144-
files: blueprint.modifiedFiles.filter((file: string) => /.ts$/.test(file))
145-
}]
146-
});
147-
}
148-
});
134+
const cwd = this.project.root;
135+
const schematicName = rawArgs[0];
136+
137+
const SchematicRunTask = require('../tasks/schematic-run').default;
138+
const schematicRunTask = new SchematicRunTask({
139+
ui: this.ui,
140+
project: this.project
141+
});
142+
143+
return schematicRunTask.run({
144+
taskOptions: commandOptions,
145+
workingDir: cwd,
146+
collectionName: this.getCollectionName(rawArgs),
147+
schematicName
148+
})
149+
},
150+
151+
printDetailedHelp: function () {
152+
const engineHost = getEngineHost();
153+
const collectionName = this.getCollectionName();
154+
const collection = getCollection(collectionName);
155+
const schematicNames: string[] = engineHost.listSchematics(collection);
156+
this.ui.writeLine(cyan('Available schematics:'));
157+
schematicNames.forEach(schematicName => {
158+
this.ui.writeLine(yellow(` ${schematicName}`));
159+
});
160+
this.ui.writeLine('');
149161
}
150162
});

0 commit comments

Comments
 (0)