Skip to content

Commit e41e10d

Browse files
clydinmgechev
authored andcommitted
feat(@angular/cli): support stable architect API
1 parent c1e7c2b commit e41e10d

File tree

2 files changed

+61
-47
lines changed

2 files changed

+61
-47
lines changed

packages/angular/cli/BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ts_library(
2525
deps = [
2626
":command_schemas",
2727
"//packages/angular_devkit/architect",
28+
"//packages/angular_devkit/architect:node",
2829
"//packages/angular_devkit/core",
2930
"//packages/angular_devkit/core:node",
3031
"//packages/angular_devkit/schematics",

packages/angular/cli/models/architect-command.ts

+60-47
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,8 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import {
9-
Architect,
10-
BuilderConfiguration,
11-
BuilderContext,
12-
TargetSpecifier,
13-
} from '@angular-devkit/architect';
8+
import { index2 } from '@angular-devkit/architect';
9+
import { WorkspaceNodeModulesArchitectHost } from '@angular-devkit/architect/node';
1410
import { experimental, json, schema, tags } from '@angular-devkit/core';
1511
import { NodeJsSyncHost } from '@angular-devkit/core/node';
1612
import { BepJsonWriter } from '../utilities/bep';
@@ -31,8 +27,8 @@ export interface ArchitectCommandOptions extends BaseCommandOptions {
3127
export abstract class ArchitectCommand<
3228
T extends ArchitectCommandOptions = ArchitectCommandOptions,
3329
> extends Command<ArchitectCommandOptions> {
34-
private _host = new NodeJsSyncHost();
35-
protected _architect: Architect;
30+
protected _architect: index2.Architect;
31+
protected _architectHost: WorkspaceNodeModulesArchitectHost;
3632
protected _workspace: experimental.workspace.Workspace;
3733
protected _registry: json.schema.SchemaRegistry;
3834

@@ -47,7 +43,13 @@ export abstract class ArchitectCommand<
4743
this._registry = new json.schema.CoreSchemaRegistry();
4844
this._registry.addPostTransform(json.schema.transforms.addUndefinedDefaults);
4945

50-
await this._loadWorkspaceAndArchitect();
46+
const workspaceLoader = new WorkspaceLoader(new NodeJsSyncHost());
47+
48+
const workspace = await workspaceLoader.loadWorkspace(this.workspace.root);
49+
this._workspace = workspace;
50+
51+
this._architectHost = new WorkspaceNodeModulesArchitectHost(workspace, this.workspace.root);
52+
this._architect = new index2.Architect(this._architectHost, this._registry);
5153

5254
if (!this.target) {
5355
if (options.help) {
@@ -67,7 +69,7 @@ export abstract class ArchitectCommand<
6769
let projectName = options.project;
6870
const targetProjectNames: string[] = [];
6971
for (const name of this._workspace.listProjectNames()) {
70-
if (this._architect.listProjectTargets(name).includes(this.target)) {
72+
if (this._workspace.getProjectTargets(name)[this.target]) {
7173
targetProjectNames.push(name);
7274
}
7375
}
@@ -85,17 +87,20 @@ export abstract class ArchitectCommand<
8587
const leftoverMap = new Map<string, { optionDefs: Option[], parsedOptions: Arguments }>();
8688
let potentialProjectNames = new Set<string>(targetProjectNames);
8789
for (const name of targetProjectNames) {
88-
const builderConfig = this._architect.getBuilderConfiguration({
90+
const builderName = await this._architectHost.getBuilderNameForTarget({
8991
project: name,
9092
target: this.target,
9193
});
9294

9395
if (this.multiTarget) {
94-
builderNames.add(builderConfig.builder);
96+
builderNames.add(builderName);
9597
}
9698

97-
const builderDesc = await this._architect.getBuilderDescription(builderConfig).toPromise();
98-
const optionDefs = await parseJsonSchemaToOptions(this._registry, builderDesc.schema);
99+
const builderDesc = await this._architectHost.resolveBuilder(builderName);
100+
const optionDefs = await parseJsonSchemaToOptions(
101+
this._registry,
102+
builderDesc.optionSchema as json.JsonObject,
103+
);
99104
const parsedOptions = parseArguments([...commandLeftovers], optionDefs);
100105
const builderLeftovers = parsedOptions['--'] || [];
101106
leftoverMap.set(name, { optionDefs, parsedOptions });
@@ -157,20 +162,20 @@ export abstract class ArchitectCommand<
157162

158163
options.project = projectName;
159164

160-
const builderConf = this._architect.getBuilderConfiguration({
165+
const builderConf = await this._architectHost.getBuilderNameForTarget({
161166
project: projectName || (targetProjectNames.length > 0 ? targetProjectNames[0] : ''),
162167
target: this.target,
163168
});
164-
const builderDesc = await this._architect.getBuilderDescription(builderConf).toPromise();
169+
const builderDesc = await this._architectHost.resolveBuilder(builderConf);
165170

166171
this.description.options.push(...(
167-
await parseJsonSchemaToOptions(this._registry, builderDesc.schema)
172+
await parseJsonSchemaToOptions(this._registry, builderDesc.optionSchema as json.JsonObject)
168173
));
169174

170175
// Update options to remove analytics from options if the builder isn't safelisted.
171176
for (const o of this.description.options) {
172177
if (o.userAnalytics) {
173-
if (!isPackageNameSafeForAnalytics(builderDesc.name)) {
178+
if (!isPackageNameSafeForAnalytics(builderConf)) {
174179
o.userAnalytics = undefined;
175180
}
176181
}
@@ -183,7 +188,8 @@ export abstract class ArchitectCommand<
183188

184189
protected async runBepTarget<T>(
185190
command: string,
186-
configuration: BuilderConfiguration<T>,
191+
configuration: index2.Target,
192+
overrides: json.JsonObject,
187193
buildEventLog: string,
188194
): Promise<number> {
189195
const bep = new BepJsonWriter(buildEventLog);
@@ -193,7 +199,12 @@ export abstract class ArchitectCommand<
193199

194200
let last = 1;
195201
let rebuild = false;
196-
await this._architect.run(configuration, { logger: this.logger }).forEach(event => {
202+
const run = await this._architect.scheduleTarget(
203+
configuration,
204+
overrides,
205+
{ logger: this.logger },
206+
);
207+
await run.output.forEach(event => {
197208
last = event.success ? 0 : 1;
198209

199210
if (rebuild) {
@@ -207,19 +218,25 @@ export abstract class ArchitectCommand<
207218
bep.writeBuildFinished(last);
208219
});
209220

221+
await run.stop();
222+
210223
return last;
211224
}
212225

213226
protected async runSingleTarget(
214-
targetSpec: TargetSpecifier,
227+
target: index2.Target,
215228
targetOptions: string[],
216-
commandOptions: ArchitectCommandOptions & Arguments) {
229+
commandOptions: ArchitectCommandOptions & Arguments,
230+
) {
217231
// We need to build the builderSpec twice because architect does not understand
218232
// overrides separately (getting the configuration builds the whole project, including
219233
// overrides).
220-
const builderConf = this._architect.getBuilderConfiguration(targetSpec);
221-
const builderDesc = await this._architect.getBuilderDescription(builderConf).toPromise();
222-
const targetOptionArray = await parseJsonSchemaToOptions(this._registry, builderDesc.schema);
234+
const builderConf = await this._architectHost.getBuilderNameForTarget(target);
235+
const builderDesc = await this._architectHost.resolveBuilder(builderConf);
236+
const targetOptionArray = await parseJsonSchemaToOptions(
237+
this._registry,
238+
builderDesc.optionSchema as json.JsonObject,
239+
);
223240
const overrides = parseArguments(targetOptions, targetOptionArray, this.logger);
224241

225242
if (overrides['--']) {
@@ -229,25 +246,26 @@ export abstract class ArchitectCommand<
229246

230247
return 1;
231248
}
232-
const realBuilderConf = this._architect.getBuilderConfiguration({ ...targetSpec, overrides });
233-
const builderContext: Partial<BuilderContext> = {
234-
logger: this.logger,
235-
targetSpecifier: targetSpec,
236-
};
237249

238250
if (commandOptions.buildEventLog && ['build', 'serve'].includes(this.description.name)) {
239251
// The build/serve commands supports BEP messaging
240252
this.logger.warn('BEP support is experimental and subject to change.');
241253

242254
return this.runBepTarget(
243255
this.description.name,
244-
realBuilderConf,
256+
target,
257+
overrides as json.JsonObject,
245258
commandOptions.buildEventLog as string,
246259
);
247260
} else {
248-
const result = await this._architect
249-
.run(realBuilderConf, builderContext)
250-
.toPromise();
261+
const run = await this._architect.scheduleTarget(
262+
target,
263+
overrides as json.JsonObject,
264+
{ logger: this.logger },
265+
);
266+
267+
const result = await run.output.toPromise();
268+
await run.stop();
251269

252270
return result.success ? 0 : 1;
253271
}
@@ -265,7 +283,11 @@ export abstract class ArchitectCommand<
265283
// Running them in parallel would jumble the log messages.
266284
let result = 0;
267285
for (const project of this.getProjectNamesByTarget(this.target)) {
268-
result |= await this.runSingleTarget({ ...targetSpec, project }, extra, options);
286+
result |= await this.runSingleTarget(
287+
{ ...targetSpec, project } as index2.Target,
288+
extra,
289+
options,
290+
);
269291
}
270292

271293
return result;
@@ -300,7 +322,7 @@ export abstract class ArchitectCommand<
300322

301323
private getProjectNamesByTarget(targetName: string): string[] {
302324
const allProjectsForTargetName = this._workspace.listProjectNames().map(projectName =>
303-
this._architect.listProjectTargets(projectName).includes(targetName) ? projectName : null,
325+
this._workspace.getProjectTargets(projectName)[targetName] ? projectName : null,
304326
).filter(x => !!x) as string[];
305327

306328
if (this.multiTarget) {
@@ -322,16 +344,7 @@ export abstract class ArchitectCommand<
322344
}
323345
}
324346

325-
private async _loadWorkspaceAndArchitect() {
326-
const workspaceLoader = new WorkspaceLoader(this._host);
327-
328-
const workspace = await workspaceLoader.loadWorkspace(this.workspace.root);
329-
330-
this._workspace = workspace;
331-
this._architect = await new Architect(workspace).loadArchitect().toPromise();
332-
}
333-
334-
private _makeTargetSpecifier(commandOptions: ArchitectCommandOptions): TargetSpecifier {
347+
private _makeTargetSpecifier(commandOptions: ArchitectCommandOptions): index2.Target {
335348
let project, target, configuration;
336349

337350
if (commandOptions.target) {
@@ -358,7 +371,7 @@ export abstract class ArchitectCommand<
358371

359372
return {
360373
project,
361-
configuration,
374+
configuration: configuration || '',
362375
target,
363376
};
364377
}

0 commit comments

Comments
 (0)