Permalink
Browse files

feat(@angular-devkit/schematics): returning a rule chains it

Instead of having to call the rule (which is an anti-pattern), the system now understands
that returning a Rule should chain it to this current Rule.

There is no way to do some pattern (like read a file to select between two Rules) without
this feature.
  • Loading branch information...
hansl committed Jun 5, 2018
1 parent c2ae7b1 commit ba3bb4138753e4a97d6b227cf7a95078a84334e0
@@ -8,7 +8,6 @@
import { JsonAstObject, JsonValue, parseJsonAst } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
Tree,
UpdateRecorder,
apply,
@@ -88,18 +87,16 @@ export default function (options: Schema): Rule {
.replace(/-/g, '_');
// Verify if we need to create a full project, or just add a new schematic.
return (tree: Tree, context: SchematicContext) => {
const source = apply(url('./project-files'), [
template({
...options as object,
dot: '.',
path,
}),
]);
const source = apply(url('./project-files'), [
template({
...options as object,
dot: '.',
path,
}),
]);
return chain([
mergeWith(source),
addPackageToMonorepo(options, path),
])(tree, context);
};
return chain([
mergeWith(source),
addPackageToMonorepo(options, path),
]);
}
@@ -33,7 +33,7 @@ function addServiceWorker(options: PwaOptions): Rule {
};
delete swOptions.title;
return externalSchematic('@schematics/angular', 'service-worker', swOptions)(host, context);
return externalSchematic('@schematics/angular', 'service-worker', swOptions);
};
}
@@ -153,7 +153,7 @@ function addManifestToAssetsConfig(options: PwaOptions) {
}
export default function (options: PwaOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return (host: Tree) => {
const workspace = getWorkspace(host);
if (!options.project) {
throw new SchematicsException('Option "project" is required.');
@@ -186,6 +186,6 @@ export default function (options: PwaOptions): Rule {
])),
updateIndexFile(options),
addManifestToAssetsConfig(options),
])(host, context);
]);
};
}
@@ -217,4 +217,4 @@ export type AsyncFileOperator = (tree: FileEntry) => Observable<FileEntry | null
* know which types is the schematic or collection metadata, as they are both tooling specific.
*/
export type Source = (context: SchematicContext) => Tree | Observable<Tree>;
export type Rule = (tree: Tree, context: SchematicContext) => Tree | Observable<Tree> | void;
export type Rule = (tree: Tree, context: SchematicContext) => Tree | Observable<Tree> | Rule | void;
@@ -83,6 +83,9 @@ export function callRule(rule: Rule,
return observableOf(inputTree);
} else if (TreeSymbol in result) {
return observableOf(result as Tree);
} else if (typeof result == 'function') {
// This is considered a Rule, chain the rule and return its output.
return callRule(result, input, context);
} else if (isObservable(result)) {
const obs = result as Observable<Tree>;
@@ -176,7 +176,7 @@ function addUniversalTarget(options: AppShellOptions): Rule {
delete universalOptions.index;
delete universalOptions.sourceDir;
return schematic('universal', universalOptions)(host, context);
return schematic('universal', universalOptions);
};
}
@@ -350,6 +350,6 @@ export default function (options: ApplicationOptions): Rule {
move(sourceDir),
]), MergeStrategy.Overwrite),
schematic('e2e', e2eOptions),
])(host, context);
]);
};
}
@@ -52,6 +52,6 @@ export default function (options: ClassOptions): Rule {
move(parsedPath.path),
]);
return branchAndMerge(mergeWith(templateSource))(host, context);
return branchAndMerge(mergeWith(templateSource));
};
}
@@ -8,7 +8,6 @@
import { strings } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
SchematicsException,
Tree,
apply,
@@ -127,7 +126,7 @@ function buildSelector(options: ComponentOptions, projectPrefix: string) {
export default function(options: ComponentOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return (host: Tree) => {
const workspace = getWorkspace(host);
if (!options.project) {
throw new SchematicsException('Option (project) is required.');
@@ -165,6 +164,6 @@ export default function(options: ComponentOptions): Rule {
addDeclarationToNgModule(options),
mergeWith(templateSource),
])),
])(host, context);
]);
};
}
@@ -8,7 +8,6 @@
import { strings } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
SchematicsException,
Tree,
apply,
@@ -103,7 +102,7 @@ function buildSelector(options: DirectiveOptions, projectPrefix: string) {
}
export default function (options: DirectiveOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return (host: Tree) => {
const workspace = getWorkspace(host);
if (!options.project) {
throw new SchematicsException('Option (project) is required.');
@@ -138,6 +137,6 @@ export default function (options: DirectiveOptions): Rule {
addDeclarationToNgModule(options),
mergeWith(templateSource),
])),
])(host, context);
]);
};
}
@@ -146,7 +146,7 @@ function validateProjectName(projectName: string) {
}
export default function (options: E2eOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return (host: Tree) => {
validateProjectName(options.name);
const workspace = getWorkspace(host);
@@ -171,6 +171,6 @@ export default function (options: E2eOptions): Rule {
}),
move(appDir),
])),
])(host, context);
]);
};
}
@@ -53,6 +53,6 @@ export default function (options: EnumOptions): Rule {
branchAndMerge(chain([
mergeWith(templateSource),
])),
])(host, context);
]);
};
}
@@ -8,7 +8,6 @@
import { strings } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
SchematicsException,
Tree,
apply,
@@ -28,7 +27,7 @@ import { Schema as GuardOptions } from './schema';
export default function (options: GuardOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return (host: Tree) => {
const workspace = getWorkspace(host);
if (!options.project) {
throw new SchematicsException('Option (project) is required.');
@@ -56,6 +55,6 @@ export default function (options: GuardOptions): Rule {
branchAndMerge(chain([
mergeWith(templateSource),
])),
])(host, context);
]);
};
}
@@ -8,7 +8,6 @@
import { strings } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
SchematicsException,
Tree,
apply,
@@ -26,7 +25,7 @@ import { Schema as InterfaceOptions } from './schema';
export default function (options: InterfaceOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return (host: Tree) => {
const workspace = getWorkspace(host);
if (!options.project) {
throw new SchematicsException('Option (project) is required.');
@@ -56,6 +55,6 @@ export default function (options: InterfaceOptions): Rule {
branchAndMerge(chain([
mergeWith(templateSource),
])),
])(host, context);
]);
};
}
@@ -257,6 +257,6 @@ export default function (options: LibraryOptions): Rule {
context.addTask(new NodePackageInstallTask());
}
},
])(host, context);
]);
};
}
@@ -786,6 +786,6 @@ export default function (): Rule {
return host;
},
])(host, context);
]);
};
}
@@ -8,7 +8,6 @@
import { basename, dirname, normalize, relative, strings } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
SchematicsException,
Tree,
apply,
@@ -72,7 +71,7 @@ function addDeclarationToNgModule(options: ModuleOptions): Rule {
}
export default function (options: ModuleOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return (host: Tree) => {
const workspace = getWorkspace(host);
if (!options.project) {
throw new SchematicsException('Option (project) is required.');
@@ -106,6 +105,6 @@ export default function (options: ModuleOptions): Rule {
addDeclarationToNgModule(options),
mergeWith(templateSource),
])),
])(host, context);
]);
};
}
@@ -8,7 +8,6 @@
import { strings } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
SchematicsException,
Tree,
apply,
@@ -87,7 +86,7 @@ function addDeclarationToNgModule(options: PipeOptions): Rule {
}
export default function (options: PipeOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return (host: Tree) => {
const workspace = getWorkspace(host);
if (!options.project) {
throw new SchematicsException('Option (project) is required.');
@@ -114,9 +113,11 @@ export default function (options: PipeOptions): Rule {
move(parsedPath.path),
]);
return branchAndMerge(chain([
return branchAndMerge(
chain([
addDeclarationToNgModule(options),
mergeWith(templateSource),
]))(host, context);
]),
);
};
}
@@ -187,6 +187,6 @@ export default function (options: ServiceWorkerOptions): Rule {
updateConfigFile(options),
addDependencies(),
updateAppModule(options),
])(host, context);
]);
};
}
@@ -8,7 +8,6 @@
import { strings } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
SchematicsException,
Tree,
apply,
@@ -25,7 +24,7 @@ import { buildDefaultPath } from '../utility/project';
import { Schema as ServiceOptions } from './schema';
export default function (options: ServiceOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return (host: Tree) => {
const workspace = getWorkspace(host);
if (!options.project) {
throw new SchematicsException('Option (project) is required.');
@@ -50,6 +49,6 @@ export default function (options: ServiceOptions): Rule {
move(parsedPath.path),
]);
return mergeWith(templateSource)(host, context);
return mergeWith(templateSource);
};
}
@@ -251,6 +251,6 @@ export default function (options: UniversalOptions): Rule {
updateConfigFile(options, tsConfigDirectory),
wrapBootstrapCall(options),
addServerTransition(options),
])(host, context);
]);
};
}
@@ -8,8 +8,6 @@
import { strings } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
Tree,
apply,
mergeWith,
template,
@@ -19,15 +17,12 @@ import { latestVersions } from '../utility/latest-versions';
import { Schema as WorkspaceOptions } from './schema';
export default function (options: WorkspaceOptions): Rule {
return (host: Tree, context: SchematicContext) => {
return mergeWith(apply(url('./files'), [
template({
utils: strings,
...options,
'dot': '.',
latestVersions,
}),
]))(host, context);
};
return mergeWith(apply(url('./files'), [
template({
utils: strings,
...options,
'dot': '.',
latestVersions,
}),
]));
}
@@ -10,11 +10,11 @@ import { SchematicsUpdateSchema } from '../schema';
export default function(options: SchematicsUpdateSchema): Rule {
return (tree: Tree, context: SchematicContext) => {
return (_tree: Tree, context: SchematicContext) => {
return chain(
context.schematic.collection.listSchematicNames()
.filter(name => name != context.schematic.description.name)
.map(name => schematic(name, options)),
)(tree, context);
);
};
}
Oops, something went wrong.

0 comments on commit ba3bb41

Please sign in to comment.