Skip to content

Commit

Permalink
feat(@angular/cli): Remove pre-processing of schematics
Browse files Browse the repository at this point in the history
This logic has been moved to the schematics so the CLI doesn't special-case anything.
  • Loading branch information
Brocco authored and hansl committed Mar 23, 2018
1 parent 2b377fc commit d57ba45
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 146 deletions.
64 changes: 13 additions & 51 deletions packages/@angular/cli/commands/generate.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import { Command, CommandScope, Option } from '../models/command';
import chalk from 'chalk';
const stringUtils = require('ember-cli-string-utils');
import { CliConfig } from '../models/config';
import {
getCollection,
getEngineHost
} from '../utilities/schematics';
import { DynamicPathOptions, dynamicPathParser } from '../utilities/dynamic-path-parser';
import { getAppFromConfig } from '../utilities/app-utils';
import * as path from 'path';
import { SchematicAvailableOptions } from '../tasks/schematic-get-options';
import { oneLine } from 'common-tags';

const { cyan } = chalk;
const separatorRegEx = /[\/\\]/g;

export default class GenerateCommand extends Command {
public readonly name = 'generate';
Expand Down Expand Up @@ -103,71 +98,38 @@ export default class GenerateCommand extends Command {
}

public run(options: any) {
let entityName = options.name;

if (entityName) {
options.name = stringUtils.dasherize(entityName.split(separatorRegEx).pop());
} else {
entityName = '';
}

const appConfig = getAppFromConfig(options.app);
const dynamicPathOptions: DynamicPathOptions = {
project: this.project,
entityName: entityName,
appConfig: appConfig,
dryRun: options.dryRun
};
const parsedPath = dynamicPathParser(dynamicPathOptions);
options.sourceDir = parsedPath.sourceDir.replace(separatorRegEx, '/');
const root = parsedPath.sourceDir + path.sep;
options.appRoot = parsedPath.appRoot === parsedPath.sourceDir ? '' :
parsedPath.appRoot.startsWith(root)
? parsedPath.appRoot.substr(root.length)
: parsedPath.appRoot;

options.path = parsedPath.dir.replace(separatorRegEx, '/');
options.path = parsedPath.dir === parsedPath.sourceDir ? '' :
parsedPath.dir.startsWith(root)
? options.path.substr(root.length)
: options.path;

const cwd = this.project.root;
const cwd = process.env.PWD;
const [collectionName, schematicName] = this.parseSchematicInfo(options);

if (['component', 'c', 'directive', 'd'].indexOf(schematicName) !== -1) {
if (options.prefix === undefined) {
options.prefix = appConfig.prefix;
}

if (schematicName === 'component' || schematicName === 'c') {
if (options.styleext === undefined) {
options.styleext = CliConfig.getValue('defaults.styleExt');
}
}
}
const workingDir = cwd.replace(this.project.root, '');
const pathOptions = this.getPathOptions(options, workingDir);
options = { ...options, ...pathOptions };

const SchematicRunTask = require('../tasks/schematic-run').default;
const schematicRunTask = new SchematicRunTask({
ui: this.ui,
project: this.project
});

if (collectionName === '@schematics/angular' && schematicName === 'interface' && options.type) {
options.type = options.type;
}

const schematicOptions = this.stripLocalOptions(options);
return schematicRunTask.run({
taskOptions: schematicOptions,
dryRun: options.dryRun,
force: options.force,
workingDir: cwd,
workingDir: this.project.root,
collectionName,
schematicName
});
}

protected getPathOptions(options: any, workingDir: string): any {
return this.options
.filter(o => o.format === 'path')
.map(o => o.name)
.filter(name => options[name] === undefined)
.reduce((acc: any, curr) => acc[curr] = workingDir, {});
}

private parseSchematicInfo(options: any) {
let collectionName: string = CliConfig.getValue('defaults.schematics.collection');

Expand Down
3 changes: 2 additions & 1 deletion packages/@angular/cli/models/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ export abstract class Option {
abstract readonly description: string;
readonly default?: string | number | boolean;
readonly required?: boolean;
abstract readonly aliases?: string[]; // (string | { [key: string]: string })[];
abstract readonly aliases?: string[];
abstract readonly type: any;
readonly format?: string;
readonly values?: any[];
readonly hidden?: boolean = false;
}
1 change: 1 addition & 0 deletions packages/@angular/cli/tasks/schematic-get-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface SchematicAvailableOptions {
description: string;
aliases: string[];
type: any;
format?: string;
schematicType: any;
schematicDefault: any;
}
Expand Down
95 changes: 1 addition & 94 deletions packages/@angular/cli/tasks/schematic-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
EmptyTree,
FileSystemSink,
FileSystemTree,
Schematic,
Tree
} from '@angular-devkit/schematics';
import { BuiltinTaskExecutor } from '@angular-devkit/schematics/tasks/node';
Expand Down Expand Up @@ -75,9 +74,6 @@ export default Task.extend({
const collection = getCollection(collectionName);
const schematic = getSchematic(collection, schematicName, options.allowPrivate);

const preppedOptions = prepOptions(schematic, taskOptions);
const opts = { ...taskOptions, ...preppedOptions };

const tree = emptyHost ? new EmptyTree() : new FileSystemTree(new FileSystemHost(workingDir));
const host = observableOf(tree);

Expand Down Expand Up @@ -131,7 +127,7 @@ export default Task.extend({
}
});

return schematic.call(opts, host).pipe(
return schematic.call(taskOptions, host).pipe(
map((tree: Tree) => Tree.optimize(tree)),
concatMap((tree: Tree) => {
return dryRunSink.commit(tree).pipe(
Expand Down Expand Up @@ -167,94 +163,5 @@ export default Task.extend({
}
return {modifiedFiles};
});
// TODO (architect): figure out what to do about lintFix
// .then((output: SchematicOutput) => {
// const modifiedFiles = output.modifiedFiles;
// const lintFix = taskOptions.lintFix !== undefined ?
// taskOptions.lintFix : CliConfig.getValue('defaults.lintFix');

// if (lintFix && modifiedFiles) {
// const LintTask = require('./lint').default;
// const lintTask = new LintTask({
// ui: this.ui,
// project: this.project
// });

// return lintTask.run({
// fix: true,
// force: true,
// silent: true,
// configs: [{
// files: modifiedFiles
// .filter((file: string) => /.ts$/.test(file))
// .map((file: string) => path.join(projectRoot, file))
// }]
// });
// }
// });
}
});

function prepOptions(schematic: Schematic<{}, {}>, options: SchematicOptions): SchematicOptions {
const properties = (<any>schematic.description).schemaJson
? (<any>schematic.description).schemaJson.properties
: options;

const keys = Object.keys(properties);
if (['component', 'c', 'directive', 'd'].indexOf(schematic.description.name) !== -1) {
options.prefix =
(options.prefix === 'false' || options.prefix === false || options.prefix === '')
? undefined : options.prefix;
}

let preppedOptions = {
...options,
...readDefaults(schematic.description.name, keys, options)
};
preppedOptions = {
...preppedOptions,
...normalizeOptions(schematic.description.name, keys, options)
};

return preppedOptions;
}

function readDefaults(schematicName: string, optionKeys: string[], options: any): any {
return optionKeys.reduce((acc: any, key) => {
const value = options[key] !== undefined ? options[key] : readDefault(schematicName, key);
if (value !== undefined) {
acc[key] = value;
}
return acc;
}, {});
}

const viewEncapsulationMap: any = {
'emulated': 'Emulated',
'native': 'Native',
'none': 'None'
};

const changeDetectionMap: any = {
'default': 'Default',
'onpush': 'OnPush'
};

function normalizeOptions(schematicName: string, optionKeys: string[], options: any): any {
return optionKeys.reduce((acc: any, key) => {

if (schematicName === 'application' || schematicName === 'component') {
if (key === 'viewEncapsulation' && options[key]) {
acc[key] = viewEncapsulationMap[options[key].toLowerCase()];
} else if (key === 'changeDetection' && options[key]) {
acc[key] = changeDetectionMap[options[key].toLowerCase()];
}
}
return acc;
}, {});
}

function readDefault(schematicName: String, key: string) {
const jsonPath = `defaults.${schematicName}.${key}`;
return CliConfig.getValue(jsonPath);
}

0 comments on commit d57ba45

Please sign in to comment.