Angular DevKit Architect is a flexible architecture for defining and executing build tasks in the Angular CLI ecosystem. It provides a job-based execution model where builders are individual units of work that can perform various tasks like building, testing, or linting Angular applications. The package exposes APIs for creating custom builders, scheduling targets, managing job execution with observables, and providing rich progress reporting.
npm install @angular-devkit/architectimport {
Architect,
createBuilder,
BuilderContext,
BuilderOutput,
Target
} from "@angular-devkit/architect";For CommonJS:
const {
Architect,
createBuilder,
BuilderContext,
BuilderOutput,
Target
} = require("@angular-devkit/architect");For jobs functionality:
import { jobs } from "@angular-devkit/architect";For testing utilities:
import { TestingArchitectHost } from "@angular-devkit/architect/testing";For Node.js integration:
import { NodeModulesArchitectHost } from "@angular-devkit/architect/node";import { Architect } from "@angular-devkit/architect";
import { NodeModulesArchitectHost } from "@angular-devkit/architect/node";
// Create an architect host for Node.js environment
const host = new NodeModulesArchitectHost(process.cwd());
const architect = new Architect(host);
// Schedule a target
const target = { project: "my-app", target: "build" };
const run = await architect.scheduleTarget(target);
// Get the build result
const result = await run.result;
console.log(result.success ? "Build succeeded" : "Build failed");
// Stop the builder
await run.stop();Angular DevKit Architect is built around several key components:
createBuilder() functionCore orchestration functionality for managing builders and scheduling targets in Angular workspaces.
class Architect {
constructor(
host: ArchitectHost,
registry?: json.schema.SchemaRegistry,
additionalJobRegistry?: Registry
);
has(name: JobName): Observable<boolean>;
scheduleBuilder(
name: string,
options: json.JsonObject,
scheduleOptions?: ScheduleOptions
): Promise<BuilderRun>;
scheduleTarget(
target: Target,
overrides?: json.JsonObject,
scheduleOptions?: ScheduleOptions
): Promise<BuilderRun>;
}
interface ScheduleOptions {
logger?: logging.Logger;
}System for creating custom builders that integrate with the Angular CLI build system.
function createBuilder<OptT = json.JsonObject, OutT extends BuilderOutput = BuilderOutput>(
fn: BuilderHandlerFn<OptT>
): Builder<OptT & json.JsonObject>;
interface BuilderHandlerFn<A> {
(input: A, context: BuilderContext): BuilderOutputLike;
}
type BuilderOutputLike = ObservableInput<BuilderOutput> | BuilderOutput;Rich context interface providing builders access to workspace information, target scheduling, and progress reporting.
interface BuilderContext {
id: number;
builder: BuilderInfo;
logger: logging.LoggerApi;
workspaceRoot: string;
currentDirectory: string;
target?: Target;
scheduleTarget(
target: Target,
overrides?: json.JsonObject,
scheduleOptions?: ScheduleOptions
): Promise<BuilderRun>;
scheduleBuilder(
builderName: string,
options?: json.JsonObject,
scheduleOptions?: ScheduleOptions
): Promise<BuilderRun>;
getTargetOptions(target: Target): Promise<json.JsonObject>;
getProjectMetadata(projectName: string): Promise<json.JsonObject>;
getBuilderNameForTarget(target: Target): Promise<string>;
validateOptions<T extends json.JsonObject = json.JsonObject>(
options: json.JsonObject,
builderName: string
): Promise<T>;
reportRunning(): void;
reportStatus(status: string): void;
reportProgress(current: number, total?: number, status?: string): void;
addTeardown(teardown: () => Promise<void> | void): void;
}Lower-level job scheduling and execution infrastructure with observables for complex build workflows.
interface Job<
ArgumentT extends JsonValue = JsonValue,
InputT extends JsonValue = JsonValue,
OutputT extends JsonValue = JsonValue
> {
readonly description: Observable<JobDescription>;
readonly argument: ArgumentT;
readonly input: Observer<InputT>;
readonly output: Observable<OutputT>;
readonly state: JobState;
getChannel<T extends JsonValue>(name: string, schema?: schema.JsonSchema): Observable<T>;
ping(): Observable<never>;
stop(): void;
}
interface Scheduler<
MinimumArgumentValueT extends JsonValue = JsonValue,
MinimumInputValueT extends JsonValue = JsonValue,
MinimumOutputValueT extends JsonValue = JsonValue
> {
getDescription(name: JobName): Observable<JobDescription | null>;
has(name: JobName): Observable<boolean>;
pause(): () => void;
schedule<A, I, O>(
name: JobName,
argument: A,
options?: ScheduleJobOptions
): Job<A, I, O>;
}
function createJobHandler<A extends JsonValue, I extends JsonValue, O extends JsonValue>(
fn: SimpleJobHandlerFn<A, I, O>,
options?: Partial<JobDescription>
): JobHandler<A, I, O>;
// Job strategies namespace
namespace strategy {
function serialize<A, I, O>(): JobStrategy<A, I, O>;
function reuse<A, I, O>(replayMessages?: boolean): JobStrategy<A, I, O>;
function memoize<A, I, O>(): JobStrategy<A, I, O>;
}Real-time progress reporting system with state management for build operations.
enum BuilderProgressState {
Stopped = "stopped",
Error = "error",
Waiting = "waiting",
Running = "running"
}
type TypedBuilderProgress =
| { state: BuilderProgressState.Stopped }
| { state: BuilderProgressState.Error; error: json.JsonValue }
| { state: BuilderProgressState.Waiting; status?: string }
| { state: BuilderProgressState.Running; status?: string; current: number; total?: number };
interface BuilderProgressReport extends BuilderProgress {
target?: Target;
builder: BuilderInfo;
}Mock hosts and testing utilities for unit testing builders and build workflows.
class TestingArchitectHost implements ArchitectHost {
addBuilder(builderName: string, builder: Builder): this;
addTarget(target: Target, builderName: string, options: json.JsonObject): this;
}
class TestProjectHost {
writeFile(path: string, content: string): void;
addTarget(project: string, target: string, builder: string, options?: json.JsonObject): void;
}Production host implementations and utilities for Node.js environments and real Angular workspaces.
class NodeModulesArchitectHost implements ArchitectHost<NodeModulesBuilderInfo> {
constructor(workspaceRoot: string, currentDirectory?: string);
getBuilderNameForTarget(target: Target): Promise<string | null>;
resolveBuilder(builderName: string): Promise<NodeModulesBuilderInfo | null>;
loadBuilder(info: NodeModulesBuilderInfo): Promise<Builder | null>;
}
interface NodeModulesBuilderInfo extends BuilderInfo {
import: string;
}
interface WorkspaceHost {
getBuilderName(project: string, target: string): Promise<string>;
getMetadata(project: string): Promise<json.JsonObject>;
getOptions(project: string, target: string, configuration?: string): Promise<json.JsonObject>;
hasTarget(project: string, target: string): Promise<boolean>;
getDefaultConfigurationName(project: string, target: string): Promise<string | undefined>;
}Utilities for converting between Target objects and string representations.
function targetStringFromTarget(target: Target): string;
function targetFromTargetString(
specifier: string,
abbreviatedProjectName?: string,
abbreviatedTargetName?: string
): Target;
function scheduleTargetAndForget(
context: BuilderContext,
target: Target,
overrides?: json.JsonObject,
scheduleOptions?: ScheduleOptions
): Observable<BuilderOutput>;
function fromAsyncIterable<T>(iterable: AsyncIterable<T>): Observable<T>;
function isBuilderOutput(obj: any): obj is BuilderOutput;interface Target extends json.JsonObject {
project: string;
target: string;
configuration?: string;
}
interface BuilderOutput extends json.JsonObject {
success: boolean;
error?: string;
}
interface BuilderRun {
id: number;
info: BuilderInfo;
result: Promise<BuilderOutput>;
lastOutput: Promise<BuilderOutput>;
output: Observable<BuilderOutput>;
progress: Observable<BuilderProgressReport>;
stop(): Promise<void>;
}
interface BuilderInfo extends json.JsonObject {
builderName: string;
description: string;
optionSchema: json.schema.JsonSchema;
}
type JobName = string;
enum JobState {
Queued = "queued",
Ready = "ready",
Started = "started",
Ended = "ended",
Errored = "errored"
}