|
6 | 6 | * found in the LICENSE file at https://angular.io/license
|
7 | 7 | */
|
8 | 8 |
|
9 |
| -import { BaseException, isPromise } from '@angular-devkit/core'; |
10 |
| -import { Observable, from, isObservable, of as observableOf, throwError } from 'rxjs'; |
11 |
| -import { defaultIfEmpty, last, mergeMap, tap } from 'rxjs/operators'; |
| 9 | +import { BaseException } from '@angular-devkit/core'; |
| 10 | +import { Observable, defer, isObservable } from 'rxjs'; |
| 11 | +import { defaultIfEmpty, mergeMap } from 'rxjs/operators'; |
12 | 12 | import { Rule, SchematicContext, Source } from '../engine/interface';
|
13 | 13 | import { Tree, TreeSymbol } from '../tree/interface';
|
14 | 14 |
|
@@ -48,67 +48,52 @@ export class InvalidSourceResultException extends BaseException {
|
48 | 48 | }
|
49 | 49 |
|
50 | 50 | export function callSource(source: Source, context: SchematicContext): Observable<Tree> {
|
51 |
| - const result = source(context); |
| 51 | + return defer(async () => { |
| 52 | + let result = source(context); |
52 | 53 |
|
53 |
| - if (isObservable(result)) { |
54 |
| - // Only return the last Tree, and make sure it's a Tree. |
55 |
| - return result.pipe( |
56 |
| - defaultIfEmpty(), |
57 |
| - last(), |
58 |
| - tap((inner) => { |
59 |
| - if (!inner || !(TreeSymbol in inner)) { |
60 |
| - throw new InvalidSourceResultException(inner); |
61 |
| - } |
62 |
| - }), |
63 |
| - ); |
64 |
| - } else if (result && TreeSymbol in result) { |
65 |
| - return observableOf(result); |
66 |
| - } else { |
67 |
| - return throwError(new InvalidSourceResultException(result)); |
68 |
| - } |
| 54 | + if (isObservable(result)) { |
| 55 | + result = await result.pipe(defaultIfEmpty()).toPromise(); |
| 56 | + } |
| 57 | + |
| 58 | + if (result && TreeSymbol in result) { |
| 59 | + return result as Tree; |
| 60 | + } |
| 61 | + |
| 62 | + throw new InvalidSourceResultException(result); |
| 63 | + }); |
69 | 64 | }
|
70 | 65 |
|
71 | 66 | export function callRule(
|
72 | 67 | rule: Rule,
|
73 | 68 | input: Tree | Observable<Tree>,
|
74 | 69 | context: SchematicContext,
|
75 | 70 | ): Observable<Tree> {
|
76 |
| - return (isObservable(input) ? input : observableOf(input)).pipe( |
77 |
| - mergeMap((inputTree) => { |
78 |
| - const result = rule(inputTree, context); |
| 71 | + if (isObservable(input)) { |
| 72 | + return input.pipe(mergeMap((inputTree) => callRuleAsync(rule, inputTree, context))); |
| 73 | + } else { |
| 74 | + return defer(() => callRuleAsync(rule, input, context)); |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +async function callRuleAsync(rule: Rule, tree: Tree, context: SchematicContext): Promise<Tree> { |
| 79 | + let result = await rule(tree, context); |
| 80 | + |
| 81 | + while (typeof result === 'function') { |
| 82 | + // This is considered a Rule, chain the rule and return its output. |
| 83 | + result = await result(tree, context); |
| 84 | + } |
| 85 | + |
| 86 | + if (typeof result === 'undefined') { |
| 87 | + return tree; |
| 88 | + } |
| 89 | + |
| 90 | + if (isObservable(result)) { |
| 91 | + result = await result.pipe(defaultIfEmpty(tree)).toPromise(); |
| 92 | + } |
| 93 | + |
| 94 | + if (TreeSymbol in result) { |
| 95 | + return result as Tree; |
| 96 | + } |
79 | 97 |
|
80 |
| - if (!result) { |
81 |
| - return observableOf(inputTree); |
82 |
| - } else if (typeof result == 'function') { |
83 |
| - // This is considered a Rule, chain the rule and return its output. |
84 |
| - return callRule(result, inputTree, context); |
85 |
| - } else if (isObservable(result)) { |
86 |
| - // Only return the last Tree, and make sure it's a Tree. |
87 |
| - return result.pipe( |
88 |
| - defaultIfEmpty(), |
89 |
| - last(), |
90 |
| - tap((inner) => { |
91 |
| - if (!inner || !(TreeSymbol in inner)) { |
92 |
| - throw new InvalidRuleResultException(inner); |
93 |
| - } |
94 |
| - }), |
95 |
| - ); |
96 |
| - } else if (isPromise(result)) { |
97 |
| - return from(result).pipe( |
98 |
| - mergeMap((inner) => { |
99 |
| - if (typeof inner === 'function') { |
100 |
| - // This is considered a Rule, chain the rule and return its output. |
101 |
| - return callRule(inner, inputTree, context); |
102 |
| - } else { |
103 |
| - return observableOf(inputTree); |
104 |
| - } |
105 |
| - }), |
106 |
| - ); |
107 |
| - } else if (TreeSymbol in result) { |
108 |
| - return observableOf(result); |
109 |
| - } else { |
110 |
| - return throwError(new InvalidRuleResultException(result)); |
111 |
| - } |
112 |
| - }), |
113 |
| - ); |
| 98 | + throw new InvalidRuleResultException(result); |
114 | 99 | }
|
0 commit comments