Skip to content

Commit 8d177e8

Browse files
clydinKeen Yee Liau
authored andcommitted
feat(@angular-devkit/schematics): support calling a task by file path when using a FileSystemEngineHost
1 parent d10f125 commit 8d177e8

File tree

7 files changed

+107
-3
lines changed

7 files changed

+107
-3
lines changed

etc/api/angular_devkit/schematics/tools/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export declare class FileSystemEngineHost extends FileSystemEngineHostBase {
4343
} | null;
4444
protected _transformCollectionDescription(name: string, desc: Partial<FileSystemCollectionDesc>): FileSystemCollectionDesc;
4545
protected _transformSchematicDescription(name: string, _collection: FileSystemCollectionDesc, desc: Partial<FileSystemSchematicDesc>): FileSystemSchematicDesc;
46+
createTaskExecutor(name: string): Observable<TaskExecutor>;
47+
hasTaskExecutor(name: string): boolean;
4648
}
4749

4850
export declare abstract class FileSystemEngineHostBase implements EngineHost<FileSystemCollectionDescription, FileSystemSchematicDescription> {

packages/angular_devkit/schematics/tools/file-system-engine-host.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
*/
88
import { existsSync } from 'fs';
99
import { join } from 'path';
10-
import { RuleFactory } from '../src';
10+
import { Observable, from, throwError } from 'rxjs';
11+
import { catchError } from 'rxjs/operators';
12+
import { RuleFactory, TaskExecutor, UnregisteredTaskException } from '../src';
1113
import { FileSystemCollectionDesc, FileSystemSchematicDesc } from './description';
1214
import { ExportStringRef } from './export-ref';
1315
import {
@@ -81,4 +83,33 @@ export class FileSystemEngineHost extends FileSystemEngineHostBase {
8183

8284
return desc as FileSystemSchematicDesc;
8385
}
86+
87+
hasTaskExecutor(name: string): boolean {
88+
if (super.hasTaskExecutor(name)) {
89+
return true;
90+
}
91+
92+
try {
93+
const maybePath = require.resolve(join(this._root, name));
94+
if (existsSync(maybePath)) {
95+
return true;
96+
}
97+
} catch {}
98+
99+
return false;
100+
}
101+
102+
createTaskExecutor(name: string): Observable<TaskExecutor> {
103+
if (!super.hasTaskExecutor(name)) {
104+
try {
105+
const path = require.resolve(join(this._root, name));
106+
107+
return from(import(path).then(mod => mod.default())).pipe(
108+
catchError(() => throwError(new UnregisteredTaskException(name))),
109+
);
110+
} catch {}
111+
}
112+
113+
return super.createTaskExecutor(name);
114+
}
84115
}

packages/angular_devkit/schematics/tools/file-system-engine-host_spec.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { normalize, virtualFs } from '@angular-devkit/core';
1010
import { HostSink, HostTree, SchematicEngine } from '@angular-devkit/schematics';
1111
import { FileSystemEngineHost } from '@angular-devkit/schematics/tools';
1212
import * as path from 'path';
13-
import { of as observableOf } from 'rxjs';
13+
import { from, of as observableOf } from 'rxjs';
1414

1515

1616
describe('FileSystemEngineHost', () => {
@@ -300,4 +300,40 @@ describe('FileSystemEngineHost', () => {
300300
})
301301
.then(done, done.fail);
302302
});
303+
304+
it('discovers a file-based task', () => {
305+
const engineHost = new FileSystemEngineHost(root);
306+
307+
expect(engineHost.hasTaskExecutor('file-tasks/file-task.js')).toBeTruthy();
308+
});
309+
310+
it('creates a file-based task', done => {
311+
const engineHost = new FileSystemEngineHost(root);
312+
313+
engineHost.createTaskExecutor('file-tasks/file-task.js').subscribe(executor => {
314+
expect(executor).toBeTruthy();
315+
from(executor(undefined, undefined as any)).toPromise().then(() => done.fail, () => done());
316+
}, done.fail);
317+
});
318+
319+
it('allows executing a schematic with a file-based task', done => {
320+
const engineHost = new FileSystemEngineHost(root);
321+
const engine = new SchematicEngine(engineHost);
322+
const host = new virtualFs.test.TestHost();
323+
324+
const collection = engine.createCollection('file-tasks');
325+
const schematic = collection.createSchematic('schematic-1');
326+
327+
schematic.call({}, observableOf(new HostTree(host))).toPromise()
328+
.then(tree => new HostSink(host).commit(tree).toPromise())
329+
.then(() => engine.executePostTasks().toPromise())
330+
.then(() => done.fail())
331+
.catch(reason => {
332+
if (reason.message === 'task exception') {
333+
done();
334+
} else {
335+
done.fail();
336+
}
337+
});
338+
});
303339
});

tests/angular_devkit/schematics/tools/file-system-engine-host/BUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ ts_library(
1616
],
1717
),
1818
data = glob(
19-
include = ["**/collection.json"],
19+
include = ["**/collection.json", "**/*.js"],
2020
),
2121
deps = [
2222
"//packages/angular_devkit/schematics",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "file-tasks",
3+
"schematics": {
4+
"schematic-1": {
5+
"description": "1",
6+
"factory": "./factory"
7+
}
8+
}
9+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
// tslint:disable-next-line:no-implicit-dependencies
9+
import { SchematicContext, Tree } from '@angular-devkit/schematics';
10+
11+
export default function() {
12+
return (_: Tree, context: SchematicContext) => {
13+
context.addTask({
14+
toConfiguration() {
15+
return { name: 'file-tasks/file-task.js' };
16+
},
17+
});
18+
};
19+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
function default_1() {
2+
return async () => {
3+
throw new Error('task exception');
4+
}
5+
}
6+
7+
exports.default = default_1;

0 commit comments

Comments
 (0)