Skip to content

Commit 0563e96

Browse files
clydinmgechev
authored andcommitted
feat(@angular-devkit/schematics): add applyToSubTree rule
This rule allows a group of rules to be applied to a scoped subdirectory of the current tree.
1 parent 4913316 commit 0563e96

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export declare function applyPathTemplate<T extends PathTemplateData>(data: T, o
3030

3131
export declare function applyTemplates<T>(options: T): Rule;
3232

33+
export declare function applyToSubtree(path: string, rules: Rule[]): Rule;
34+
3335
export declare function asSource(rule: Rule): Source;
3436

3537
export declare type AsyncFileOperator = (tree: FileEntry) => Observable<FileEntry | null>;

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

+19
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { SchematicsException } from '../exception/exception';
1212
import { FilteredTree } from '../tree/filtered';
1313
import { FilterHostTree, HostTree } from '../tree/host-tree';
1414
import { FileEntry, FilePredicate, MergeStrategy, Tree } from '../tree/interface';
15+
import { ScopedTree } from '../tree/scoped';
1516
import {
1617
branch,
1718
empty as staticEmpty,
@@ -202,3 +203,21 @@ export function composeFileOperators(operators: FileOperator[]): FileOperator {
202203
return current;
203204
};
204205
}
206+
207+
export function applyToSubtree(path: string, rules: Rule[]): Rule {
208+
return (tree, context) => {
209+
const scoped = new ScopedTree(tree, path);
210+
211+
return callRule(chain(rules), observableOf(scoped), context).pipe(
212+
map(result => {
213+
if (result === scoped) {
214+
return tree;
215+
} else {
216+
throw new SchematicsException(
217+
'Original tree must be returned from all rules when using "applyToSubtree".',
218+
);
219+
}
220+
}),
221+
);
222+
};
223+
}

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

+20-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ import { of as observableOf } from 'rxjs';
1717
import { Rule, SchematicContext, Source } from '../engine/interface';
1818
import { Tree } from '../tree/interface';
1919
import { empty } from '../tree/static';
20-
import { apply, chain } from './base';
20+
import { apply, applyToSubtree, chain } from './base';
2121
import { callRule, callSource } from './call';
22+
import { move } from './move';
2223

2324

2425
const context: SchematicContext = {
@@ -163,3 +164,21 @@ describe('partitionApplyMerge', () => {
163164
.then(done, done.fail);
164165
});
165166
});
167+
168+
describe('applyToSubtree', () => {
169+
it('works', done => {
170+
const tree = new HostTree();
171+
tree.create('a/b/file1', 'hello world');
172+
tree.create('a/b/file2', 'hello world');
173+
tree.create('a/c/file3', 'hello world');
174+
175+
callRule(applyToSubtree('a/b', [move('x')]), observableOf(tree), context)
176+
.toPromise()
177+
.then(result => {
178+
expect(result.exists('a/b/x/file1')).toBe(true);
179+
expect(result.exists('a/b/x/file2')).toBe(true);
180+
expect(result.exists('a/c/file3')).toBe(true);
181+
})
182+
.then(done, done.fail);
183+
});
184+
});

0 commit comments

Comments
 (0)