Skip to content

Commit 991daff

Browse files
hanslAngular Builds
authored and
Angular Builds
committed
wip: .
1 parent 811b596 commit 991daff

File tree

8 files changed

+159
-110
lines changed

8 files changed

+159
-110
lines changed

packages/angular_devkit/architect/builders/builders.json

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
{
2-
"$schema": "../architect/src/builders-schema.json",
3-
"version": 2,
2+
"$schema": "../src/builders-schema.json",
43
"builders": {
54
"true": {
5+
"version": 2,
66
"implementation": "./true",
77
"schema": "./noop-schema.json",
88
"description": "Always succeed."
99
},
1010
"false": {
11+
"version": 2,
1112
"implementation": "./false",
1213
"schema": "./noop-schema.json",
1314
"description": "Always fails."
1415
},
1516
"and": {
17+
"version": 2,
1618
"implementation": "./and",
17-
"schema": "./and-schema.json",
19+
"schema": "./operator-schema.json",
1820
"description": "A builder that executes many builders in parallel, and succeed if both succeeds."
1921
}
2022
}

packages/angular_devkit/architect/node/node-modules-architect-host.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import { experimental, json } from '@angular-devkit/core';
99
import { resolve } from '@angular-devkit/core/node';
1010
import * as path from 'path';
11-
import { ArchitectHost, BuilderInfo } from '../src/api';
11+
import { ArchitectHost, BuilderInfo, BuilderJobHandler, BuilderSymbol } from '../src/api';
1212
import { Schema as BuilderSchema } from '../src/builders-schema';
1313
import { Target } from '../src/input-schema';
1414

@@ -51,7 +51,7 @@ export class WorkspaceNodeModulesArchitectHost implements ArchitectHost {
5151
const builderJsonPath = path.resolve(path.dirname(packageJsonPath), packageJson['builders']);
5252
const builderJson = require(builderJsonPath) as BuilderSchema;
5353

54-
const builder = builderJson.builders[builderName];
54+
const builder = builderJson.builders && builderJson.builders[builderName];
5555

5656
if (!builder) {
5757
throw new Error('Cannot find builder.');
@@ -92,4 +92,13 @@ export class WorkspaceNodeModulesArchitectHost implements ArchitectHost {
9292
...(target.configuration ? targetSpec['configurations'][target.configuration] : 0),
9393
};
9494
}
95+
96+
async loadBuilder(info: BuilderInfo): Promise<BuilderJobHandler> {
97+
const builder = (await import(info.import)).default;
98+
if (builder[BuilderSymbol]) {
99+
return builder.handler;
100+
}
101+
102+
throw new Error('Builder is not a builder');
103+
}
95104
}

packages/angular_devkit/architect/src/api.ts

+65-78
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import { experimental, isPromise, json, logging } from '@angular-devkit/core';
9-
import { Observable, from, isObservable, of } from 'rxjs';
9+
import { Observable, from, isObservable, of, Observer } from 'rxjs';
1010
import { concatMap, first, map, shareReplay, switchMap, tap } from 'rxjs/operators';
11-
import { JobInboundMessageKind, JobOutboundMessageKind } from '../../core/src/experimental/jobs';
12-
import { Schema as RealBuilderInput, Target } from './input-schema';
11+
import { JobInboundMessageKind } from '../../core/src/experimental/jobs';
12+
import { Schema as RealBuilderInput, Target as RealTarget } from './input-schema';
1313
import { Schema as RealBuilderOutput } from './output-schema';
14-
import { Schema as RealBuilderProgress } from './progress-schema';
14+
import { Schema as RealBuilderProgress, State as BuilderProgressState } from './progress-schema';
1515

16-
export type Target = Target;
16+
export type Target = json.JsonObject & RealTarget;
1717

1818
// Type short hands.
1919
export type BuilderJobHandler<
@@ -27,9 +27,15 @@ export type BuilderRegistry<
2727
O extends BuilderOutput = BuilderOutput,
2828
> = experimental.jobs.Registry<A, I, O>;
2929

30+
export type TypedBuilderProgress =
31+
{ state: BuilderProgressState.Stopped }
32+
| { state: BuilderProgressState.Error; error: json.JsonValue; }
33+
| { state: BuilderProgressState.Waiting; status?: string; }
34+
| { state: BuilderProgressState.Running; status?: string; current: number; total?: number; }
35+
3036
export type BuilderInput = json.JsonObject & RealBuilderInput;
3137
export type BuilderOutput = json.JsonObject & RealBuilderOutput;
32-
export type BuilderProgress = json.JsonObject & RealBuilderProgress;
38+
export type BuilderProgress = RealBuilderProgress & TypedBuilderProgress;
3339

3440
const inputSchema = require('./input-schema.json');
3541
const outputSchema = require('./output-schema.json');
@@ -55,7 +61,7 @@ export const VersionSymbol = Symbol.for('@angular-devkit/architect:version');
5561

5662

5763
export interface Builder<OptionT extends json.JsonObject> {
58-
handler: experimental.jobs.JobHandler<boolean, BuilderInput, BuilderOutput>;
64+
handler: experimental.jobs.JobHandler<json.JsonObject, BuilderInput, BuilderOutput>;
5965
[BuilderSymbol]: true;
6066
[VersionSymbol]: string;
6167
}
@@ -79,7 +85,7 @@ export interface BuilderContext {
7985
// dependencies?: BuilderRun[];
8086

8187
// bep: Observer<BuildEventMessage>
82-
// progress: Observer<{ current: number; total: number }>;
88+
progress(progress: BuilderProgress): void;
8389

8490
// building: () => void;
8591
}
@@ -122,6 +128,8 @@ export interface ArchitectHost {
122128
getWorkspaceRoot(): string;
123129

124130
getOptionsForTarget(target: Target): Promise<json.JsonObject>;
131+
132+
loadBuilder(info: BuilderInfo): Promise<BuilderJobHandler>;
125133
}
126134

127135
/**
@@ -154,11 +162,17 @@ async function _scheduleTarget(
154162
reason: 'initial',
155163
options: overrides,
156164
target,
157-
} as BuilderInput);
165+
});
158166
}
159167
});
160168
} else {
161-
169+
job.input.next({
170+
currentDirectory: options.workspaceRoot,
171+
workspaceRoot: options.currentDirectory,
172+
reason: 'schedule',
173+
options: overrides,
174+
target,
175+
});
162176
}
163177

164178
job.outboundBus.subscribe(
@@ -181,70 +195,42 @@ async function _scheduleTarget(
181195
export function createBuilder<OptT extends json.JsonObject>(
182196
fn: BuilderHandlerFn<OptT>,
183197
): Builder<OptT> {
184-
function handler(
185-
options: boolean,
186-
context: experimental.jobs.JobHandlerContext<boolean, BuilderInput, BuilderOutput>,
187-
) {
188-
const description = context.description;
198+
const cjh = experimental.jobs.createJobHandler;
199+
const handler = cjh<json.JsonObject, BuilderInput, BuilderOutput>((options, context) => {
189200
const scheduler = context.scheduler;
190-
191-
return new Observable<experimental.jobs.JobOutboundMessage<BuilderOutput>>(observer => {
192-
const logger = new logging.Logger('job');
193-
logger.subscribe(entry => {
194-
observer.next({
195-
kind: JobOutboundMessageKind.Log,
196-
description,
197-
entry,
198-
});
199-
});
200-
201-
context.inboundBus.subscribe(x => {
202-
if (x.kind === experimental.jobs.JobInboundMessageKind.Input) {
203-
const i = x.value;
204-
const context: BuilderContext = {
205-
workspaceRoot: i.workspaceRoot,
206-
currentDirectory: i.currentDirectory,
207-
target: i.target,
208-
logger,
209-
scheduleTarget(target: Target, overrides: json.JsonObject) {
210-
return _scheduleTarget(target, overrides, scheduler, {
211-
logger,
212-
workspaceRoot: i.workspaceRoot,
213-
currentDirectory: i.currentDirectory,
214-
});
215-
},
216-
};
217-
218-
let result = fn(i.options as OptT, context);
219-
220-
if (isPromise(result)) {
221-
result = from(result);
222-
} else if (!isObservable(result)) {
223-
result = of(result);
224-
}
225-
226-
result.subscribe(
227-
value => observer.next({
228-
kind: experimental.jobs.JobOutboundMessageKind.Output,
229-
description,
230-
value,
231-
}),
232-
err => observer.error(err),
233-
() => observer.complete(),
234-
);
201+
const logger = context.logger;
202+
203+
return new Observable<BuilderOutput>(observer => {
204+
context.input.subscribe(i => {
205+
const context: BuilderContext = {
206+
workspaceRoot: i.workspaceRoot,
207+
currentDirectory: i.currentDirectory,
208+
target: i.target as Target,
209+
logger: logger,
210+
scheduleTarget(target: Target, overrides: json.JsonObject) {
211+
return _scheduleTarget(target, overrides, scheduler, {
212+
logger: logger.createChild(''),
213+
workspaceRoot: i.workspaceRoot,
214+
currentDirectory: i.currentDirectory,
215+
});
216+
},
217+
};
218+
219+
let result = fn(i.options as OptT, context);
220+
221+
if (isPromise(result)) {
222+
result = from(result);
223+
} else if (!isObservable(result)) {
224+
result = of(result);
235225
}
236-
});
237226

238-
// The job is ready to listen.
239-
observer.next({
240-
description,
241-
kind: experimental.jobs.JobOutboundMessageKind.Start,
227+
return result.subscribe(observer);
242228
});
243229
});
244-
}
230+
});
245231

246232
return {
247-
handler: Object.assign(handler, { jobDescription: {} }),
233+
handler,
248234
[BuilderSymbol]: true,
249235
[VersionSymbol]: require('../package.json').version,
250236
};
@@ -253,6 +239,7 @@ export function createBuilder<OptT extends json.JsonObject>(
253239
function _createBackwardCompatibleJobHandlerFromBuilderInfo(
254240
info: BuilderInfo,
255241
target: Target | undefined,
242+
host: ArchitectHost,
256243
registry: json.schema.SchemaRegistry,
257244
baseOptions: json.JsonObject,
258245
): Observable<BuilderJobHandler | null> {
@@ -263,6 +250,7 @@ function _createBackwardCompatibleJobHandlerFromBuilderInfo(
263250
return from(module.createBackwardCompatibleJobHandlerFromBuilderInfo(
264251
info,
265252
target,
253+
host,
266254
registry,
267255
baseOptions,
268256
));
@@ -273,6 +261,7 @@ function _createBackwardCompatibleJobHandlerFromBuilderInfo(
273261
function _createJobHandlerFromBuilderInfo(
274262
info: BuilderInfo,
275263
_target: Target | undefined,
264+
host: ArchitectHost,
276265
registry: json.schema.SchemaRegistry,
277266
baseOptions: json.JsonObject,
278267
): Observable<BuilderJobHandler> {
@@ -284,15 +273,6 @@ function _createJobHandlerFromBuilderInfo(
284273
info,
285274
};
286275

287-
const loader = async () => {
288-
const builder = (await import(info.import)).default;
289-
if (builder[BuilderSymbol]) {
290-
return builder.handler;
291-
}
292-
293-
throw new Error('Builder is not a builder');
294-
};
295-
296276
function handler(argument: json.JsonObject, context: experimental.jobs.JobHandlerContext) {
297277
const inboundBus = context.inboundBus.pipe(
298278
concatMap(message => {
@@ -323,7 +303,7 @@ function _createJobHandlerFromBuilderInfo(
323303
}),
324304
);
325305

326-
return from(loader()).pipe(
306+
return from(host.loadBuilder(info)).pipe(
327307
switchMap(fn => fn(argument, { ...context, inboundBus })),
328308
);
329309
}
@@ -372,10 +352,17 @@ export class ArchitectBuilderJobRegistry implements BuilderRegistry {
372352
result = _createBackwardCompatibleJobHandlerFromBuilderInfo(
373353
info,
374354
target,
355+
this._host,
375356
this._registry,
376357
options || {});
377358
} else {
378-
result = _createJobHandlerFromBuilderInfo(info, target, this._registry, options || {});
359+
result = _createJobHandlerFromBuilderInfo(
360+
info,
361+
target,
362+
this._host,
363+
this._registry,
364+
options || {},
365+
);
379366
}
380367

381368
if (cache) {

packages/angular_devkit/architect/src/backward-compatible.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import * as fs from 'fs';
2020
import { Observable, concat, from, of } from 'rxjs';
2121
import { concatMap, ignoreElements, map, mergeMap, switchMap, tap } from 'rxjs/operators';
2222
import {
23+
ArchitectHost,
2324
BuilderDescription,
2425
BuilderInfo,
2526
BuilderInput,
@@ -73,6 +74,7 @@ class BackwardCompatibleArchitect implements ArchitectPublicInterface {
7374
private _workspace: experimental.workspace.Workspace,
7475
private _root: Path,
7576
private _scheduler: experimental.jobs.Scheduler,
77+
private _host: ArchitectHost,
7678
) {}
7779

7880
asArchitect() {
@@ -107,7 +109,6 @@ class BackwardCompatibleArchitect implements ArchitectPublicInterface {
107109
const info = (desc as BuilderDescription).info;
108110

109111
const builderModule = require(info.import);
110-
// tslint:disable-next-line:no-non-null-assertion
111112
this._builderConstructorMap.set(builderName, builderModule['default']);
112113
}),
113114
);
@@ -251,6 +252,7 @@ class BackwardCompatibleArchitect implements ArchitectPublicInterface {
251252
export async function createBackwardCompatibleJobHandlerFromBuilderInfo(
252253
info: BuilderInfo,
253254
target: Target | undefined,
255+
architectHost: ArchitectHost,
254256
registry: json.schema.SchemaRegistry,
255257
baseOptions: json.JsonObject,
256258
): Promise<BuilderJobHandler> {
@@ -296,6 +298,7 @@ export async function createBackwardCompatibleJobHandlerFromBuilderInfo(
296298
workspace,
297299
root,
298300
context.scheduler,
301+
architectHost,
299302
) as {} as legacy.Architect;
300303

301304
instance = new ClassImpl({

0 commit comments

Comments
 (0)