Skip to content

Commit 3fc5202

Browse files
clydinKeen Yee Liau
authored andcommitted
refactor(@angular-devkit/schematics): update rxjs usage in rules
rxjs has improved over time and this updates the rules to take advantage of improvements where applicable.
1 parent 01247c9 commit 3fc5202

File tree

3 files changed

+40
-58
lines changed

3 files changed

+40
-58
lines changed

etc/api/angular_devkit/schematics/src/_golden-api.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export interface BaseWorkflowOptions {
6767

6868
export declare function branchAndMerge(rule: Rule, strategy?: MergeStrategy): Rule;
6969

70-
export declare function callRule(rule: Rule, input: Observable<Tree>, context: SchematicContext): Observable<Tree>;
70+
export declare function callRule(rule: Rule, input: Tree | Observable<Tree>, context: SchematicContext): Observable<Tree>;
7171

7272
export declare function callSource(source: Source, context: SchematicContext): Observable<Tree>;
7373

packages/angular_devkit/schematics/src/rules/base.ts

Lines changed: 33 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,75 +5,65 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { Observable, of as observableOf } from 'rxjs';
9-
import { concatMap, last, map } from 'rxjs/operators';
10-
import { FileOperator, Rule, SchematicContext, Source } from '../engine/interface';
8+
import { Observable, concat } from 'rxjs';
9+
import { map, mapTo, toArray } from 'rxjs/operators';
10+
import { FileOperator, Rule, Source } from '../engine/interface';
1111
import { SchematicsException } from '../exception/exception';
1212
import { FilterHostTree, HostTree } from '../tree/host-tree';
1313
import { FileEntry, FilePredicate, MergeStrategy, Tree } from '../tree/interface';
1414
import { ScopedTree } from '../tree/scoped';
15-
import {
16-
branch,
17-
empty as staticEmpty,
18-
merge as staticMerge,
19-
partition as staticPartition,
20-
} from '../tree/static';
15+
import { empty as staticEmpty, partition } from '../tree/static';
2116
import { callRule, callSource } from './call';
2217

23-
2418
/**
2519
* A Source that returns an tree as its single value.
2620
*/
2721
export function source(tree: Tree): Source {
2822
return () => tree;
2923
}
3024

31-
3225
/**
3326
* A source that returns an empty tree.
3427
*/
3528
export function empty(): Source {
3629
return () => staticEmpty();
3730
}
3831

39-
4032
/**
4133
* Chain multiple rules into a single rule.
4234
*/
4335
export function chain(rules: Rule[]): Rule {
44-
return (tree: Tree, context: SchematicContext) => {
45-
return rules.reduce((acc: Observable<Tree>, curr: Rule) => {
46-
return callRule(curr, acc, context);
47-
}, observableOf(tree));
36+
return (tree, context) => {
37+
return rules.reduce(
38+
(acc: Tree | Observable<Tree>, curr: Rule) => callRule(curr, acc, context),
39+
tree,
40+
);
4841
};
4942
}
5043

51-
5244
/**
5345
* Apply multiple rules to a source, and returns the source transformed.
5446
*/
5547
export function apply(source: Source, rules: Rule[]): Source {
5648
return context => callRule(chain(rules), callSource(source, context), context);
5749
}
5850

59-
6051
/**
6152
* Merge an input tree with the source passed in.
6253
*/
6354
export function mergeWith(source: Source, strategy: MergeStrategy = MergeStrategy.Default): Rule {
64-
return (tree: Tree, context: SchematicContext) => {
65-
const result = callSource(source, context);
66-
67-
return result.pipe(map(other => staticMerge(tree, other, strategy || context.strategy)));
55+
return (tree, context) => {
56+
return callSource(source, context).pipe(
57+
map(sourceTree => tree.merge(sourceTree, strategy || context.strategy)),
58+
mapTo(tree),
59+
);
6860
};
6961
}
7062

71-
7263
export function noop(): Rule {
7364
return () => {};
7465
}
7566

76-
7767
export function filter(predicate: FilePredicate<boolean>): Rule {
7868
return ((tree: Tree) => {
7969
if (HostTree.isHostTree(tree)) {
@@ -84,25 +74,19 @@ export function filter(predicate: FilePredicate<boolean>): Rule {
8474
});
8575
}
8676

87-
8877
export function asSource(rule: Rule): Source {
89-
return apply(empty(), [rule]);
78+
return context => callRule(rule, staticEmpty(), context);
9079
}
9180

92-
9381
export function branchAndMerge(rule: Rule, strategy = MergeStrategy.Default): Rule {
94-
return (tree: Tree, context: SchematicContext) => {
95-
const branchedTree = branch(tree);
96-
97-
return callRule(rule, observableOf(branchedTree), context)
98-
.pipe(
99-
last(),
100-
map(t => staticMerge(tree, t, strategy)),
101-
);
82+
return (tree, context) => {
83+
return callRule(rule, tree.branch(), context).pipe(
84+
map(branch => tree.merge(branch, strategy || context.strategy)),
85+
mapTo(tree),
86+
);
10287
};
10388
}
10489

105-
10690
export function when(predicate: FilePredicate<boolean>, operator: FileOperator): FileOperator {
10791
return (entry: FileEntry) => {
10892
if (predicate(entry.path, entry)) {
@@ -113,30 +97,28 @@ export function when(predicate: FilePredicate<boolean>, operator: FileOperator):
11397
};
11498
}
11599

116-
117100
export function partitionApplyMerge(
118101
predicate: FilePredicate<boolean>,
119102
ruleYes: Rule,
120103
ruleNo?: Rule,
121104
): Rule {
122-
return (tree: Tree, context: SchematicContext) => {
123-
const [yes, no] = staticPartition(tree, predicate);
105+
return (tree, context) => {
106+
const [yes, no] = partition(tree, predicate);
124107

125-
if (!ruleNo) {
126-
// Shortcut.
127-
return callRule(ruleYes, observableOf(staticPartition(tree, predicate)[0]), context)
128-
.pipe(map(yesTree => staticMerge(yesTree, no, context.strategy)));
129-
}
108+
return concat(
109+
callRule(ruleYes, yes, context),
110+
callRule(ruleNo || noop(), no, context),
111+
).pipe(
112+
toArray(),
113+
map(([yesTree, noTree]) => {
114+
yesTree.merge(noTree, context.strategy);
130115

131-
return callRule(ruleYes, observableOf(yes), context)
132-
.pipe(concatMap(yesTree => {
133-
return callRule(ruleNo, observableOf(no), context)
134-
.pipe(map(noTree => staticMerge(yesTree, noTree, context.strategy)));
135-
}));
116+
return yesTree;
117+
}),
118+
);
136119
};
137120
}
138121

139-
140122
export function forEach(operator: FileOperator): Rule {
141123
return (tree: Tree) => {
142124
tree.visit((path, entry) => {
@@ -182,7 +164,7 @@ export function applyToSubtree(path: string, rules: Rule[]): Rule {
182164
return (tree, context) => {
183165
const scoped = new ScopedTree(tree, path);
184166

185-
return callRule(chain(rules), observableOf(scoped), context).pipe(
167+
return callRule(chain(rules), scoped, context).pipe(
186168
map(result => {
187169
if (result === scoped) {
188170
return tree;

packages/angular_devkit/schematics/src/rules/call.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { BaseException, isObservable, isPromise } from '@angular-devkit/core';
9-
import { Observable, from, of as observableOf, throwError } from 'rxjs';
8+
import { BaseException, isPromise } from '@angular-devkit/core';
9+
import { Observable, from, isObservable, of as observableOf, throwError } from 'rxjs';
1010
import { defaultIfEmpty, last, mergeMap, tap } from 'rxjs/operators';
1111
import { Rule, SchematicContext, Source } from '../engine/interface';
1212
import { Tree, TreeSymbol } from '../tree/interface';
@@ -74,17 +74,17 @@ export function callSource(source: Source, context: SchematicContext): Observabl
7474

7575
export function callRule(
7676
rule: Rule,
77-
input: Observable<Tree>,
77+
input: Tree | Observable<Tree>,
7878
context: SchematicContext,
7979
): Observable<Tree> {
80-
return input.pipe(mergeMap(inputTree => {
80+
return (isObservable(input) ? input : observableOf(input)).pipe(mergeMap(inputTree => {
8181
const result = rule(inputTree, context);
8282

8383
if (!result) {
8484
return observableOf(inputTree);
8585
} else if (typeof result == 'function') {
8686
// This is considered a Rule, chain the rule and return its output.
87-
return callRule(result, observableOf(inputTree), context);
87+
return callRule(result, inputTree, context);
8888
} else if (isObservable(result)) {
8989
// Only return the last Tree, and make sure it's a Tree.
9090
return result.pipe(
@@ -101,7 +101,7 @@ export function callRule(
101101
mergeMap(inner => {
102102
if (typeof inner === 'function') {
103103
// This is considered a Rule, chain the rule and return its output.
104-
return callRule(inner, observableOf(inputTree), context);
104+
return callRule(inner, inputTree, context);
105105
} else {
106106
return observableOf(inputTree);
107107
}

0 commit comments

Comments
 (0)