Skip to content

Commit 5e3095e

Browse files
committed
feat(@angular-devkit/schematics): change schema validation to AJV
1 parent 609f8e2 commit 5e3095e

File tree

18 files changed

+542
-94
lines changed

18 files changed

+542
-94
lines changed

package-lock.json

Lines changed: 20 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"@types/source-map": "^0.5.0",
5656
"@types/webpack": "^3.0.2",
5757
"@types/webpack-sources": "^0.1.3",
58+
"ajv": "^5.5.1",
5859
"chokidar": "^1.7.0",
5960
"conventional-changelog": "^1.1.0",
6061
"glob": "^7.0.3",

packages/angular_devkit/schematics/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
],
1818
"dependencies": {
1919
"@angular-devkit/core": "0.0.0",
20-
"@ngtools/json-schema": "^1.1.0"
20+
"@ngtools/json-schema": "^1.1.0",
21+
"ajv": "~5.5.1"
2122
},
2223
"peerDependencies": {
2324
"rxjs": "^5.5.2"

packages/angular_devkit/schematics/src/engine/engine.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
import { BaseException, logging } from '@angular-devkit/core';
99
import { CollectionDescription, TypedSchematicContext } from '@angular-devkit/schematics';
10-
import 'rxjs/add/operator/map';
10+
import { Observable } from 'rxjs/Observable';
1111
import { Url } from 'url';
1212
import { MergeStrategy } from '../tree/interface';
1313
import { NullTree } from '../tree/null';
@@ -124,11 +124,10 @@ export class SchematicEngine<CollectionT extends object, SchematicT extends obje
124124
}
125125

126126
transformOptions<OptionT extends object, ResultT extends object>(
127-
schematic: Schematic<CollectionT, SchematicT>, options: OptionT): ResultT {
128-
return this._host.transformOptions<OptionT, ResultT>(
129-
schematic.description,
130-
options,
131-
);
127+
schematic: Schematic<CollectionT, SchematicT>,
128+
options: OptionT,
129+
): Observable<ResultT> {
130+
return this._host.transformOptions<OptionT, ResultT>(schematic.description, options);
132131
}
133132

134133
createSourceFromUrl(url: Url, context: TypedSchematicContext<CollectionT, SchematicT>): Source {

packages/angular_devkit/schematics/src/engine/interface.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export interface EngineHost<CollectionMetadataT extends object, SchematicMetadat
5555
transformOptions<OptionT extends object, ResultT extends object>(
5656
schematic: SchematicDescription<CollectionMetadataT, SchematicMetadataT>,
5757
options: OptionT,
58-
): ResultT;
58+
): Observable<ResultT>;
5959

6060
readonly defaultMergeStrategy?: MergeStrategy;
6161
}
@@ -88,7 +88,7 @@ export interface Engine<CollectionMetadataT extends object, SchematicMetadataT e
8888
transformOptions<OptionT extends object, ResultT extends object>(
8989
schematic: Schematic<CollectionMetadataT, SchematicMetadataT>,
9090
options: OptionT,
91-
): ResultT;
91+
): Observable<ResultT>;
9292

9393
readonly defaultMergeStrategy: MergeStrategy;
9494
}

packages/angular_devkit/schematics/src/engine/schematic.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import { BaseException } from '@angular-devkit/core';
99
import { Observable } from 'rxjs/Observable';
1010
import 'rxjs/add/observable/of';
1111
import 'rxjs/add/operator/concatMap';
12+
import { concatMap } from 'rxjs/operators/concatMap';
13+
import { first } from 'rxjs/operators/first';
14+
import { map } from 'rxjs/operators/map';
1215
import { callRule } from '../rules/call';
1316
import { Tree } from '../tree/interface';
1417
import {
@@ -49,8 +52,16 @@ export class SchematicImpl<CollectionT extends object, SchematicT extends object
4952
parentContext?: Partial<TypedSchematicContext<CollectionT, SchematicT>>,
5053
): Observable<Tree> {
5154
const context = this._engine.createContext(this, parentContext);
52-
const transformedOptions = this._engine.transformOptions(this, options);
5355

54-
return callRule(this._factory(transformedOptions), host, context);
56+
return host
57+
.pipe(
58+
first(),
59+
concatMap(tree => this._engine.transformOptions(this, options).pipe(
60+
map(o => [tree, o]),
61+
)),
62+
concatMap(([tree, transformedOptions]: [Tree, OptionT]) => {
63+
return callRule(this._factory(transformedOptions), Observable.of(tree), context);
64+
}),
65+
);
5566
}
5667
}

packages/angular_devkit/schematics/src/engine/schematic_spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const context = {
3333
};
3434
const engine: Engine<CollectionT, SchematicT> = {
3535
createContext: (schematic: Schematic<{}, {}>) => ({ engine, schematic, ...context }),
36-
transformOptions: (_: {}, options: {}) => options,
36+
transformOptions: (_: {}, options: {}) => Observable.of(options),
3737
defaultMergeStrategy: MergeStrategy.Default,
3838
} as {} as Engine<CollectionT, SchematicT>;
3939
const collection = {

packages/angular_devkit/schematics/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import { FilePredicate, MergeStrategy } from './tree/interface';
9-
import {Tree as TreeInterface } from './tree/interface';
9+
import { Tree as TreeInterface } from './tree/interface';
1010
import { branch, empty, merge, optimize, partition } from './tree/static';
1111

1212

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

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { BaseException } from '@angular-devkit/core';
99
import { Observable } from 'rxjs/Observable';
1010
import { _throw } from 'rxjs/observable/throw';
1111
import { last } from 'rxjs/operators/last';
12+
import { mergeMap } from 'rxjs/operators/mergeMap';
1213
import { tap } from 'rxjs/operators/tap';
1314
import { Rule, SchematicContext, Source } from '../engine/interface';
1415
import { Tree, TreeSymbol } from '../tree/interface';
@@ -83,29 +84,31 @@ export function callSource(source: Source, context: SchematicContext): Observabl
8384
export function callRule(rule: Rule,
8485
input: Observable<Tree>,
8586
context: SchematicContext): Observable<Tree> {
86-
return input.mergeMap(inputTree => {
87-
const result = rule(inputTree, context) as object;
87+
return input.pipe(
88+
mergeMap(inputTree => {
89+
const result = rule(inputTree, context) as object;
8890

89-
if (result === undefined) {
90-
return Observable.of(inputTree);
91-
} else if (TreeSymbol in result) {
92-
return Observable.of(result as Tree);
93-
} else if (Symbol.observable in result) {
94-
const obs = result as Observable<Tree>;
91+
if (result === undefined) {
92+
return Observable.of(inputTree);
93+
} else if (TreeSymbol in result) {
94+
return Observable.of(result as Tree);
95+
} else if (Symbol.observable in result) {
96+
const obs = result as Observable<Tree>;
9597

96-
// Only return the last Tree, and make sure it's a Tree.
97-
return obs.pipe(
98-
last(),
99-
tap(inner => {
100-
if (!(TreeSymbol in inner)) {
101-
throw new InvalidRuleResultException(inner);
102-
}
103-
}),
104-
);
105-
} else if (result === undefined) {
106-
return Observable.of(inputTree);
107-
} else {
108-
return _throw(new InvalidRuleResultException(result));
109-
}
110-
});
98+
// Only return the last Tree, and make sure it's a Tree.
99+
return obs.pipe(
100+
last(),
101+
tap(inner => {
102+
if (!(TreeSymbol in inner)) {
103+
throw new InvalidRuleResultException(inner);
104+
}
105+
}),
106+
);
107+
} else if (result === undefined) {
108+
return Observable.of(inputTree);
109+
} else {
110+
return _throw(new InvalidRuleResultException(result));
111+
}
112+
}),
113+
);
111114
}

packages/angular_devkit/schematics/src/tree/interface.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ export interface Tree {
105105
}
106106

107107

108+
namespace Tree {
109+
export function isTree(maybeTree: object): maybeTree is Tree {
110+
return TreeSymbol in maybeTree;
111+
}
112+
}
113+
114+
108115
export interface UpdateRecorder {
109116
// These just record changes.
110117
insertLeft(index: number, content: Buffer | string): UpdateRecorder;

0 commit comments

Comments
 (0)