0
# Task Management
1
2
Core task management functionality providing the main Listr class for orchestrating task execution, context sharing, concurrent processing, and lifecycle management.
3
4
## Capabilities
5
6
### Listr Class
7
8
The main class for creating and managing task lists with full type safety and extensive configuration options.
9
10
```typescript { .api }
11
/**
12
* Main class for creating and managing task lists
13
* @template Ctx - Context type shared between tasks
14
* @template Renderer - Primary renderer type
15
* @template FallbackRenderer - Fallback renderer type
16
*/
17
class Listr<
18
Ctx = ListrContext,
19
Renderer extends ListrRendererValue = ListrPrimaryRendererValue,
20
FallbackRenderer extends ListrRendererValue = ListrSecondaryRendererValue
21
> {
22
/** Array of tasks to execute */
23
public tasks: Task<Ctx, ListrGetRendererClassFromValue<Renderer>, ListrGetRendererClassFromValue<FallbackRenderer>>[];
24
/** Collected errors from task execution */
25
public errors: ListrError<Ctx>[];
26
/** Shared context object between tasks */
27
public ctx: Ctx;
28
/** Event manager instance */
29
public events: ListrEventManager;
30
/** Current execution path */
31
public path: string[];
32
/** Selected renderer class */
33
public rendererClass: ListrRendererFactory;
34
/** Options for the current renderer */
35
public rendererClassOptions: ListrGetRendererOptions<ListrGetRendererClassFromValue<Renderer> | ListrGetRendererClassFromValue<FallbackRenderer>>;
36
/** Current renderer selection state */
37
public rendererSelection: ListrRendererSelection;
38
39
/**
40
* Create a new task list
41
* @param task - Single task or array of tasks to execute
42
* @param options - Configuration options for the task list
43
* @param parentTask - Parent task if this is a subtask list
44
*/
45
constructor(
46
task: ListrTask<Ctx, ListrGetRendererClassFromValue<Renderer>, ListrGetRendererClassFromValue<FallbackRenderer>>
47
| ListrTask<Ctx, ListrGetRendererClassFromValue<Renderer>, ListrGetRendererClassFromValue<FallbackRenderer>>[],
48
options?: ListrBaseClassOptions<Ctx, Renderer, FallbackRenderer>,
49
parentTask?: Task<any, ListrGetRendererClassFromValue<Renderer>, ListrGetRendererClassFromValue<FallbackRenderer>>
50
);
51
52
/**
53
* Check if this is the root task list
54
* @returns true if this is the root task list
55
*/
56
isRoot(): boolean;
57
58
/**
59
* Check if this is a subtask of another task list
60
* @returns true if this is a subtask
61
*/
62
isSubtask(): boolean;
63
64
/**
65
* Add tasks to the current task list
66
* @param tasks - Single task or array of tasks to add
67
*/
68
add(tasks: ListrTask<Ctx, ListrGetRendererClassFromValue<Renderer>> | ListrTask<Ctx, ListrGetRendererClassFromValue<Renderer>>[]): void;
69
70
/**
71
* Execute the task list
72
* @param context - Initial context to pass to tasks
73
* @returns Promise resolving to the final context
74
*/
75
run(context?: Ctx): Promise<Ctx>;
76
}
77
```
78
79
### Task Wrapper Class
80
81
User-facing API wrapper for task manipulation during execution, providing methods for output, state control, and subtask creation.
82
83
```typescript { .api }
84
/**
85
* Task wrapper providing user-facing API for task manipulation
86
* @template Ctx - Context type
87
* @template Renderer - Renderer type
88
* @template FallbackRenderer - Fallback renderer type
89
*/
90
class TaskWrapper<Ctx, Renderer, FallbackRenderer> {
91
/** Get or set the task title */
92
title: string | any[];
93
/** Get or set the task output */
94
output: string | any[];
95
96
/**
97
* Create a new subtask list
98
* @param task - Task or array of tasks for the subtask list
99
* @param options - Options for the subtask list
100
* @returns New Listr instance for subtasks
101
*/
102
newListr(
103
task: ListrTask<Ctx, Renderer> | ListrTask<Ctx, Renderer>[],
104
options?: ListrBaseClassOptions<Ctx, any, any>
105
): Listr<Ctx, any, any>;
106
107
/**
108
* Report an error for the current task
109
* @param error - Error to report
110
* @param type - Type of error for categorization
111
*/
112
report(error: Error, type?: ListrErrorTypes): void;
113
114
/**
115
* Skip the current task with an optional message
116
* @param message - Optional skip message
117
*/
118
skip(message?: string): void;
119
120
/**
121
* Check whether this task is currently in a retry state
122
* @returns Retry state information or { count: 0 } if not retrying
123
*/
124
isRetrying(): Task['retry'];
125
126
/**
127
* Create a new prompt for getting user input through the prompt adapter
128
* @param adapter - Prompt adapter constructor
129
* @returns Prompt adapter instance
130
*/
131
prompt<T extends ListrPromptAdapter = ListrPromptAdapter>(
132
adapter: new (task: Task<Ctx, Renderer, FallbackRenderer>, wrapper: TaskWrapper<Ctx, Renderer, FallbackRenderer>) => T
133
): T;
134
135
/**
136
* Get stdout stream for process output capture
137
* @param type - Output type for the stream
138
* @returns Stdout stream
139
*/
140
stdout(type?: ListrTaskEventType.OUTPUT | ListrTaskEventType.PROMPT): NodeJS.WritableStream;
141
}
142
```
143
144
### Internal Task Class
145
146
Internal task representation with state management and lifecycle control.
147
148
```typescript { .api }
149
/**
150
* Internal task representation with state management
151
* @template Ctx - Context type
152
* @template Renderer - Renderer type
153
* @template FallbackRenderer - Fallback renderer type
154
*/
155
class Task<Ctx, Renderer, FallbackRenderer> {
156
/** Unique task identifier */
157
public id: string;
158
/** Current task state */
159
public state: ListrTaskState;
160
/** Task title */
161
public title?: string;
162
/** Task output */
163
public output?: string;
164
/** Child/subtasks array */
165
public subtasks: Task<Ctx, Renderer, FallbackRenderer>[];
166
/** Retry configuration */
167
public retry?: ListrTaskRetry;
168
/** Message channel for task communication */
169
public message: ListrTaskMessage;
170
/** Current prompt instance */
171
public prompt: ListrTaskPrompt;
172
/** Associated Listr instance */
173
public listr: Listr<Ctx, any, any>;
174
175
/**
176
* Check if task should be enabled
177
* @param ctx - Current context
178
* @returns Promise resolving to boolean indicating if task is enabled
179
*/
180
check(ctx: Ctx): Promise<boolean>;
181
182
/**
183
* Check if task is in pending state
184
* @returns true if task is pending
185
*/
186
isPending(): boolean;
187
188
/**
189
* Check if task is in running state
190
* @returns true if task is running
191
*/
192
isRunning(): boolean;
193
194
/**
195
* Check if task has completed successfully
196
* @returns true if task has completed
197
*/
198
isCompleted(): boolean;
199
200
/**
201
* Check if task has failed
202
* @returns true if task has failed
203
*/
204
isFailed(): boolean;
205
206
/**
207
* Check if task was skipped
208
* @returns true if task was skipped
209
*/
210
isSkipped(): boolean;
211
212
/**
213
* Check if task is in retry state
214
* @returns true if task is retrying
215
*/
216
isRetrying(): boolean;
217
218
/**
219
* Check if task is rolling back
220
* @returns true if task is rolling back
221
*/
222
isRollingBack(): boolean;
223
224
/**
225
* Check if task has been rolled back
226
* @returns true if task has been rolled back
227
*/
228
isRolledBack(): boolean;
229
230
/**
231
* Pause task execution for specified time
232
* @param time - Time to pause in milliseconds
233
* @returns Promise that resolves when pause is complete
234
*/
235
pause(time: number): Promise<void>;
236
}
237
```
238
239
**Usage Examples:**
240
241
```typescript
242
import { Listr } from "listr2";
243
244
interface MyContext {
245
files: string[];
246
results: any[];
247
}
248
249
// Basic task list with typed context
250
const tasks = new Listr<MyContext>([
251
{
252
title: "Scanning files",
253
task: (ctx, task) => {
254
// Simulate file scanning
255
return new Promise(resolve => {
256
setTimeout(() => {
257
ctx.files = ["file1.js", "file2.js", "file3.js"];
258
task.output = `Found ${ctx.files.length} files`;
259
resolve(undefined);
260
}, 1000);
261
});
262
}
263
},
264
{
265
title: "Processing files",
266
task: (ctx, task) => {
267
// Create subtasks for each file
268
return task.newListr(
269
ctx.files.map(file => ({
270
title: `Processing ${file}`,
271
task: async (subCtx) => {
272
// Simulate processing
273
await new Promise(resolve => setTimeout(resolve, 500));
274
subCtx.results = subCtx.results || [];
275
subCtx.results.push(`processed-${file}`);
276
}
277
})),
278
{ concurrent: true }
279
);
280
}
281
}
282
]);
283
284
// Run with initial context
285
const result = await tasks.run({ files: [], results: [] });
286
console.log("Processing complete:", result.results);
287
```
288
289
### Concurrency Control
290
291
```typescript
292
import { Listr } from "listr2";
293
294
// Sequential execution (default)
295
const sequential = new Listr([
296
{ title: "Task 1", task: () => Promise.resolve() },
297
{ title: "Task 2", task: () => Promise.resolve() },
298
{ title: "Task 3", task: () => Promise.resolve() }
299
]);
300
301
// Concurrent execution
302
const concurrent = new Listr([
303
{ title: "Task 1", task: () => Promise.resolve() },
304
{ title: "Task 2", task: () => Promise.resolve() },
305
{ title: "Task 3", task: () => Promise.resolve() }
306
], { concurrent: true });
307
308
// Limited concurrency
309
const limitedConcurrent = new Listr([
310
{ title: "Task 1", task: () => Promise.resolve() },
311
{ title: "Task 2", task: () => Promise.resolve() },
312
{ title: "Task 3", task: () => Promise.resolve() },
313
{ title: "Task 4", task: () => Promise.resolve() }
314
], { concurrent: 2 }); // Max 2 tasks running simultaneously
315
```
316
317
## Types
318
319
```typescript { .api }
320
interface ListrBaseClassOptions<Ctx, Renderer, FallbackRenderer> {
321
/** Initial context to pass to tasks */
322
ctx?: Ctx;
323
/** Enable concurrent execution or set concurrency limit */
324
concurrent?: boolean | number;
325
/** Exit immediately when a task fails */
326
exitOnError?: boolean;
327
/** Exit after rollback operations complete */
328
exitAfterRollback?: boolean;
329
/** Error collection mode */
330
collectErrors?: false | 'minimal' | 'full';
331
/** Register signal listeners for graceful shutdown */
332
registerSignalListeners?: boolean;
333
/** Primary renderer to use */
334
renderer?: Renderer;
335
/** Fallback renderer when primary is unavailable */
336
fallbackRenderer?: FallbackRenderer;
337
/** Options for the primary renderer */
338
rendererOptions?: ListrGetRendererOptions<ListrGetRendererClassFromValue<Renderer>>;
339
/** Options for the fallback renderer */
340
fallbackRendererOptions?: ListrGetRendererOptions<ListrGetRendererClassFromValue<FallbackRenderer>>;
341
/** Condition to determine when to use fallback renderer */
342
fallbackRendererCondition?: boolean | (() => boolean);
343
/** Condition to determine when to use silent renderer */
344
silentRendererCondition?: boolean | (() => boolean);
345
/** Force TTY mode even when not detected */
346
forceTTY?: boolean;
347
/** Force Unicode support even when not detected */
348
forceUnicode?: boolean;
349
}
350
351
type ListrContext = Record<PropertyKey, any>;
352
353
type ListrPrimaryRendererValue = 'default';
354
type ListrSecondaryRendererValue = 'simple';
355
356
enum ListrRendererSelection {
357
PRIMARY = 'PRIMARY',
358
SECONDARY = 'SECONDARY',
359
SILENT = 'SILENT'
360
}
361
```