0
# Task Execution
1
2
Task execution system for running executors, parsing targets, and integrating with Nx's task graph for intelligent build orchestration.
3
4
## Capabilities
5
6
### Executor Execution
7
8
Run executors programmatically with full context and option support.
9
10
```typescript { .api }
11
/**
12
* Run an executor with the specified target and options
13
* @param targetDescription - Target specification (project:target:configuration)
14
* @param options - Executor options
15
* @param context - Execution context
16
* @returns Async iterator of execution results
17
*/
18
function runExecutor<T = any>(
19
targetDescription: Target,
20
options: T,
21
context: ExecutorContext
22
): Promise<AsyncIterableIterator<any>>;
23
24
/**
25
* Target specification interface
26
*/
27
interface Target {
28
/** Project name */
29
project: string;
30
/** Target name within the project */
31
target: string;
32
/** Optional configuration variant */
33
configuration?: string;
34
}
35
36
/**
37
* Context provided to executors during execution
38
*/
39
interface ExecutorContext {
40
/** Workspace root directory */
41
root: string;
42
/** Current working directory */
43
cwd: string;
44
/** Complete workspace configuration */
45
workspace: WorkspaceJsonConfiguration;
46
/** Whether verbose logging is enabled */
47
isVerbose: boolean;
48
/** Currently executing project name */
49
projectName?: string;
50
/** Currently executing target name */
51
targetName?: string;
52
/** Currently executing configuration name */
53
configurationName?: string;
54
/** Project graph for dependency analysis */
55
projectGraph?: ProjectGraph;
56
/** Name of the task runner being used */
57
taskRunner?: string;
58
}
59
```
60
61
**Usage Examples:**
62
63
```typescript
64
import { runExecutor, ExecutorContext } from "@nx/devkit";
65
66
async function buildProject(context: ExecutorContext) {
67
const target = {
68
project: "my-app",
69
target: "build",
70
configuration: "production"
71
};
72
73
const options = {
74
outputPath: "dist/my-app",
75
optimization: true,
76
sourceMap: false
77
};
78
79
// Run the build executor
80
const result = await runExecutor(target, options, context);
81
82
// Process results
83
for await (const res of result) {
84
if (res.success) {
85
console.log("Build succeeded");
86
} else {
87
console.error("Build failed:", res.error);
88
}
89
}
90
}
91
```
92
93
### Target String Parsing
94
95
Parse and format target strings for programmatic target manipulation.
96
97
```typescript { .api }
98
/**
99
* Parse a target string into component parts
100
* @param targetString - String in format "project:target:configuration"
101
* @param executorContext - Execution context for project validation
102
* @returns Parsed target object
103
*/
104
function parseTargetString(
105
targetString: string,
106
executorContext: ExecutorContext
107
): Target;
108
109
/**
110
* Convert target object to string representation
111
* @param target - Target object to convert
112
* @returns String in format "project:target:configuration"
113
*/
114
function targetToTargetString(target: Target): string;
115
```
116
117
**Usage Examples:**
118
119
```typescript
120
import { parseTargetString, targetToTargetString, ExecutorContext } from "@nx/devkit";
121
122
function processTargets(context: ExecutorContext) {
123
// Parse target strings
124
const buildTarget = parseTargetString("my-app:build:production", context);
125
console.log(buildTarget); // { project: "my-app", target: "build", configuration: "production" }
126
127
const testTarget = parseTargetString("my-lib:test", context);
128
console.log(testTarget); // { project: "my-lib", target: "test" }
129
130
// Convert back to strings
131
const buildString = targetToTargetString(buildTarget);
132
console.log(buildString); // "my-app:build:production"
133
134
const testString = targetToTargetString(testTarget);
135
console.log(testString); // "my-lib:test"
136
}
137
```
138
139
### Target Options Resolution
140
141
Read and resolve target options with configuration merging and inheritance.
142
143
```typescript { .api }
144
/**
145
* Read and combine options for a given target
146
* Merges default options with configuration-specific options
147
* @param target - Target specification
148
* @param context - Execution context
149
* @returns Resolved target options
150
*/
151
function readTargetOptions<T = any>(
152
target: Target,
153
context: ExecutorContext
154
): T;
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
import { readTargetOptions, ExecutorContext, Target } from "@nx/devkit";
161
162
function getResolvedOptions(context: ExecutorContext) {
163
const target: Target = {
164
project: "my-app",
165
target: "build",
166
configuration: "production"
167
};
168
169
// Get merged options for the target
170
const options = readTargetOptions(target, context);
171
172
console.log("Resolved build options:", options);
173
// Result includes:
174
// - Base options from target.options
175
// - Configuration-specific options from target.configurations.production
176
// - Any inherited or computed values
177
}
178
```
179
180
## Executor Types
181
182
### Core Executor Interfaces
183
184
```typescript { .api }
185
/**
186
* Standard executor function signature
187
* Returns iterator of execution results
188
*/
189
type Executor<T = any> = (
190
options: T,
191
context: ExecutorContext
192
) => Promise<{ success: boolean; [key: string]: any }> | AsyncIterableIterator<{ success: boolean; [key: string]: any }>;
193
194
/**
195
* Promise-based executor signature
196
* Returns single result promise
197
*/
198
type PromiseExecutor<T = any> = (
199
options: T,
200
context: ExecutorContext
201
) => Promise<{ success: boolean; [key: string]: any }>;
202
203
/**
204
* Async iterator executor signature
205
* Yields multiple results during execution
206
*/
207
type AsyncIteratorExecutor<T = any> = (
208
options: T,
209
context: ExecutorContext
210
) => AsyncIterableIterator<{ success: boolean; [key: string]: any }>;
211
212
/**
213
* Task graph-aware executor signature
214
* Has access to the complete task graph
215
*/
216
type TaskGraphExecutor<T = any> = (
217
taskGraph: TaskGraph,
218
options: Record<string, T>,
219
overrides: T,
220
context: ExecutorContext
221
) => Promise<Record<string, { success: boolean; [key: string]: any }>>;
222
```
223
224
### Executor Configuration
225
226
```typescript { .api }
227
/**
228
* Schema definition for executors.json
229
*/
230
interface ExecutorsJson {
231
executors?: Record<string, ExecutorDescription>;
232
builders?: Record<string, ExecutorDescription>; // Legacy support
233
}
234
235
interface ExecutorDescription {
236
/** Path to executor implementation */
237
implementation?: string;
238
/** Path to schema JSON file */
239
schema?: string;
240
/** Whether executor is hidden from help */
241
hidden?: boolean;
242
/** Description of the executor */
243
description?: string;
244
}
245
```
246
247
### Custom Hashing
248
249
```typescript { .api }
250
/**
251
* Custom hasher interface for cache key generation
252
*/
253
interface CustomHasher {
254
(task: Task, context: HasherContext): Promise<Hash> | Hash;
255
}
256
257
/**
258
* Context provided to custom hashers
259
*/
260
interface HasherContext {
261
hasher: Hasher;
262
projectGraph: ProjectGraph;
263
taskGraph: TaskGraph;
264
workspaceConfig: WorkspaceJsonConfiguration;
265
}
266
267
type Hash = string;
268
```
269
270
### Framework Integration
271
272
```typescript { .api }
273
/**
274
* Convert Nx executor to Angular DevKit builder
275
* @param executor - Nx executor function
276
* @returns Angular DevKit builder
277
*/
278
function convertNxExecutor(executor: Executor): any;
279
```
280
281
## Advanced Executor Patterns
282
283
### Streaming Results
284
285
```typescript
286
// Example executor that yields multiple results
287
export default async function* myExecutor(
288
options: MyExecutorOptions,
289
context: ExecutorContext
290
): AsyncIterableIterator<{ success: boolean; [key: string]: any }> {
291
292
yield { success: false, message: "Starting compilation..." };
293
294
try {
295
// Perform compilation steps
296
const compilationResult = await compile(options);
297
yield { success: true, message: "Compilation complete" };
298
299
// Perform additional steps
300
const optimizationResult = await optimize(compilationResult);
301
yield { success: true, message: "Optimization complete", artifacts: optimizationResult };
302
303
} catch (error) {
304
yield { success: false, error: error.message };
305
}
306
}
307
```
308
309
### Task Dependencies
310
311
```typescript
312
// Example using task dependencies in executor context
313
export default async function myExecutor(
314
options: MyExecutorOptions,
315
context: ExecutorContext
316
): Promise<{ success: boolean }> {
317
318
// Access project graph for dependency analysis
319
const projectGraph = context.projectGraph;
320
const dependencies = projectGraph?.dependencies[context.projectName!] || [];
321
322
// Run dependency targets first
323
for (const dep of dependencies) {
324
const depTarget = { project: dep.target, target: "build" };
325
await runExecutor(depTarget, {}, context);
326
}
327
328
// Run main task
329
const result = await performMainTask(options);
330
return { success: result.success };
331
}
332
```
333
334
### Configuration Inheritance
335
336
```typescript
337
// Example of complex option resolution
338
function resolveExecutorOptions(
339
target: Target,
340
context: ExecutorContext
341
): ResolvedOptions {
342
343
const baseOptions = readTargetOptions(target, context);
344
345
// Apply environment-specific overrides
346
const envOverrides = process.env.NODE_ENV === 'production'
347
? { optimize: true, minify: true }
348
: { sourceMap: true, watch: true };
349
350
return {
351
...baseOptions,
352
...envOverrides
353
};
354
}
355
```