or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

command-execution.mdcommand-line.mdconfiguration.mdcore-generator.mdfile-system.mdgit-integration.mdindex.mdpackage-management.mdtask-lifecycle.mduser-interaction.md

task-lifecycle.mddocs/

0

# Task & Lifecycle Management

1

2

Queue-based task execution system with custom priorities, composition, and lifecycle management that orchestrates generator method execution and composition with other generators.

3

4

## Capabilities

5

6

### Task Queuing

7

8

Core task management system for scheduling and executing generator methods.

9

10

```typescript { .api }

11

/**

12

* Schedule tasks on a run queue

13

* @param task - Task configuration object

14

*/

15

queueTask(task: Task): void;

16

17

/**

18

* Schedule methods on a run queue

19

* @param method - Method to be scheduled or object with function properties

20

* @param methodName - Name of the method (task) to be scheduled

21

* @param queueName - Name of the queue to be scheduled on

22

* @param reject - Reject callback for error handling

23

*/

24

queueMethod(method: Task['method'], methodName: string, queueName: string, reject?: Task['reject']): void;

25

queueMethod(method: Record<string, Task['method']>, methodName?: string | Task['reject'], reject?: Task['reject']): void;

26

27

/**

28

* Schedule tasks from a group on a run queue

29

* @param taskGroup - Object containing tasks

30

* @param taskOptions - Task configuration options

31

*/

32

queueTaskGroup(taskGroup: Record<string, Task['method']>, taskOptions: TaskOptions): void;

33

```

34

35

**Usage Examples:**

36

37

```typescript

38

export default class MyGenerator extends Generator {

39

initializing() {

40

// Queue a single task

41

this.queueTask({

42

method: async () => {

43

this.log('Custom initialization task');

44

await this.checkEnvironment();

45

},

46

taskName: 'check-environment',

47

queueName: 'initializing'

48

});

49

50

// Queue method by name

51

this.queueMethod(

52

this.setupDependencies.bind(this),

53

'setup-dependencies',

54

'configuring'

55

);

56

57

// Queue multiple methods from object

58

this.queueTaskGroup({

59

validateInput: () => this.validateAnswers(),

60

createDirectories: () => this.setupFolders(),

61

copyBaseFiles: () => this.copyTemplates()

62

}, { queueName: 'writing' });

63

}

64

65

async checkEnvironment() {

66

// Custom task implementation

67

}

68

69

setupDependencies() {

70

// Custom method implementation

71

}

72

}

73

```

74

75

### Lifecycle Management

76

77

Methods for managing the generator lifecycle and execution flow.

78

79

```typescript { .api }

80

/**

81

* Schedule every generator's methods on a run queue

82

* Analyzes generator prototype and queues methods matching lifecycle phases

83

* @param taskOptions - Configuration for task execution

84

*/

85

queueOwnTasks(taskOptions: TaskOptions): void;

86

87

/**

88

* Schedule a generator's method on a run queue

89

* @param name - The method name to schedule

90

* @param taskOptions - Task configuration options

91

*/

92

queueOwnTask(name: string, taskOptions: TaskOptions): void;

93

94

/**

95

* Execute a task with error handling and lifecycle events

96

* @param task - Task to be executed

97

* @param args - Task arguments

98

* @param taskStatus - Task status for cancellation support

99

*/

100

async executeTask(task: Task, args?: any[], taskStatus?: TaskStatus): Promise<void>;

101

102

/**

103

* Get available task names from generator prototype

104

* @returns Array of valid method names that can be queued

105

*/

106

getTaskNames(): string[];

107

```

108

109

**Usage Example:**

110

111

```typescript

112

export default class MyGenerator extends Generator {

113

constructor(args, opts) {

114

super(args, opts);

115

116

// Configure task behavior

117

this.setFeatures({

118

tasksMatchingPriority: true, // Only queue methods matching lifecycle phases

119

taskPrefix: 'task_', // Methods must start with 'task_'

120

inheritTasks: true // Include parent class methods

121

});

122

}

123

124

// These methods will be automatically queued

125

task_initializing() {

126

this.log('Custom initializing task');

127

}

128

129

task_prompting() {

130

return this.prompt([...]);

131

}

132

133

task_writing() {

134

this.renderTemplate('template.ejs', 'output.js');

135

}

136

137

// This method won't be queued (doesn't match prefix)

138

helperMethod() {

139

return 'helper';

140

}

141

142

// Get available tasks

143

listTasks() {

144

const tasks = this.getTaskNames();

145

this.log(`Available tasks: ${tasks.join(', ')}`);

146

// Output: Available tasks: initializing, prompting, writing

147

}

148

}

149

```

150

151

### Priority and Queue Management

152

153

Manage custom execution priorities and queue ordering.

154

155

```typescript { .api }

156

/**

157

* Register custom priorities for this generator

158

* @param priorities - Array of priority configurations

159

*/

160

registerPriorities(priorities: Priority[]): void;

161

162

/**

163

* Extract tasks from a priority queue

164

* @param name - Priority/queue name

165

* @param taskOptions - Task configuration options

166

* @returns Array of tasks from the priority

167

*/

168

extractTasksFromPriority(name: string, taskOptions?: TaskOptions): Task[];

169

170

/**

171

* Extract tasks from a task group object

172

* @param group - Object containing task methods

173

* @param taskOptions - Task configuration options

174

* @returns Array of individual tasks

175

*/

176

extractTasksFromGroup(group: Record<string, Task['method']>, taskOptions: TaskOptions): Task[];

177

```

178

179

**Usage Examples:**

180

181

```typescript

182

export default class MyGenerator extends Generator {

183

constructor(args, opts) {

184

super(args, opts);

185

186

// Register custom priorities

187

this.registerPriorities([

188

{

189

priorityName: 'validation',

190

before: 'prompting' // Run before prompting phase

191

},

192

{

193

priorityName: 'cleanup',

194

queueName: 'custom-cleanup-queue',

195

before: 'end' // Run before end phase

196

}

197

]);

198

}

199

200

// Custom priority methods

201

validation() {

202

this.log('Running validation phase');

203

this.validateEnvironment();

204

}

205

206

cleanup() {

207

this.log('Running cleanup phase');

208

this.removeTemporaryFiles();

209

}

210

211

// Extract and manipulate tasks

212

customTaskHandling() {

213

const validationTasks = this.extractTasksFromPriority('validation');

214

const groupTasks = this.extractTasksFromGroup({

215

step1: () => this.log('Step 1'),

216

step2: () => this.log('Step 2'),

217

step3: () => this.log('Step 3')

218

}, { queueName: 'custom' });

219

220

// Queue extracted tasks with custom options

221

groupTasks.forEach(task => this.queueTask({

222

...task,

223

once: true // Only run once per generator instance

224

}));

225

}

226

}

227

```

228

229

### Generator Composition

230

231

Compose with other generators to create complex scaffolding workflows.

232

233

```typescript { .api }

234

/**

235

* Compose this generator with another one

236

* @param generator - Path to generator module or generator object

237

* @param options - Composition options

238

* @returns Promise resolving to composed generator instance(s)

239

*/

240

async composeWith<G extends BaseGenerator = BaseGenerator>(

241

generator: string | { Generator: any; path: string },

242

options?: ComposeOptions<G>

243

): Promise<G>;

244

245

async composeWith<G extends BaseGenerator = BaseGenerator>(

246

generator: string[],

247

options?: ComposeOptions<G>

248

): Promise<G[]>;

249

250

async composeWith<G extends BaseGenerator = BaseGenerator>(

251

generator: string | { Generator: any; path: string },

252

args: string[],

253

options?: Partial<GetGeneratorOptions<G>>,

254

immediately?: boolean

255

): Promise<G>;

256

```

257

258

**Usage Examples:**

259

260

```typescript

261

export default class MyGenerator extends Generator {

262

async initializing() {

263

// Compose with a peerDependency generator

264

await this.composeWith('bootstrap', {

265

sass: true,

266

version: '5.0'

267

});

268

269

// Compose with local generator

270

await this.composeWith(

271

path.resolve(__dirname, '../generator-component/app/main.js'),

272

{ componentType: 'functional' }

273

);

274

275

// Compose with multiple generators

276

await this.composeWith([

277

'typescript',

278

'eslint',

279

'prettier'

280

], {

281

skipInstall: this.options.skipInstall

282

});

283

284

// Compose with arguments

285

await this.composeWith(

286

'sub-generator',

287

['component', 'Button'],

288

{ typescript: true }

289

);

290

}

291

292

async writing() {

293

// Compose with Generator class directly

294

const SubGenerator = await import('./sub-generator.js');

295

await this.composeWith({

296

Generator: SubGenerator.default,

297

path: './sub-generator.js'

298

}, {

299

forwardOptions: true // Forward all options

300

});

301

}

302

}

303

```

304

305

### Task Cancellation and Restart

306

307

Manage task cancellation and generator restart functionality.

308

309

```typescript { .api }

310

/**

311

* Ignore cancellable tasks

312

* Marks current task status as cancelled to skip remaining cancellable tasks

313

*/

314

cancelCancellableTasks(): void;

315

316

/**

317

* Start the generator again with new options

318

* @param options - New options to merge with existing ones

319

*/

320

startOver(options?: BaseOptions): void;

321

322

/**

323

* Queue generator tasks (main entry point for task scheduling)

324

*/

325

async queueTasks(): Promise<void>;

326

```

327

328

**Usage Examples:**

329

330

```typescript

331

export default class MyGenerator extends Generator {

332

async prompting() {

333

this.answers = await this.prompt([

334

{

335

type: 'confirm',

336

name: 'continueAdvanced',

337

message: 'Continue with advanced setup?'

338

}

339

]);

340

341

if (!this.answers.continueAdvanced) {

342

// Cancel remaining cancellable tasks

343

this.cancelCancellableTasks();

344

return;

345

}

346

}

347

348

// This task can be cancelled

349

writing() {

350

this.queueTask({

351

method: () => {

352

this.log('This task can be cancelled');

353

this.renderTemplate('advanced.ejs', 'advanced.js');

354

},

355

taskName: 'advanced-setup',

356

queueName: 'writing',

357

cancellable: true

358

});

359

}

360

361

// Restart scenario

362

async handleError() {

363

try {

364

await this.someFailingOperation();

365

} catch (error) {

366

this.log('Setup failed, restarting with safe defaults...');

367

this.startOver({

368

safeMode: true,

369

skipAdvanced: true

370

});

371

}

372

}

373

}

374

```

375

376

### Pipeline Operations

377

378

File processing pipelines with transform streams.

379

380

```typescript { .api }

381

/**

382

* Process files through transform streams

383

* @param options - Pipeline configuration options

384

* @param transforms - Array of transform streams to apply

385

*/

386

async pipeline(

387

options?: GeneratorPipelineOptions,

388

...transforms: Array<FileTransform<MemFsEditorFile>>

389

): Promise<void>;

390

391

/**

392

* Add a transform stream to the commit stream

393

* @param options - Pipeline options with priority configuration

394

* @param transforms - Transform streams to queue

395

* @returns This generator for chaining

396

*/

397

queueTransformStream(

398

options?: GeneratorPipelineOptions & { priorityToQueue?: string },

399

...transforms: Array<FileTransform<MemFsEditorFile>>

400

): this;

401

```

402

403

**Usage Examples:**

404

405

```typescript

406

import { Transform } from 'stream';

407

408

export default class MyGenerator extends Generator {

409

writing() {

410

// Copy files first

411

this.copyTemplate('src/**/*', 'src/');

412

413

// Queue transform pipeline

414

this.queueTransformStream(

415

{ priorityToQueue: 'transform' },

416

new Transform({

417

objectMode: true,

418

transform(file, encoding, callback) {

419

if (file.path.endsWith('.js')) {

420

// Add strict mode to JS files

421

file.contents = Buffer.from(

422

`'use strict';\n${file.contents.toString()}`

423

);

424

}

425

callback(null, file);

426

}

427

})

428

);

429

}

430

431

async install() {

432

// Run pipeline directly

433

await this.pipeline(

434

{ name: 'Post-install processing' },

435

new Transform({

436

objectMode: true,

437

transform(file, encoding, callback) {

438

if (file.path.includes('node_modules')) {

439

// Skip node_modules

440

return callback();

441

}

442

callback(null, file);

443

}

444

})

445

);

446

}

447

}

448

```

449

450

## Types

451

452

```typescript { .api }

453

interface Task<TaskContext = any> {

454

method: (this: TaskContext, ...args: any[]) => unknown | Promise<unknown>;

455

taskName: string;

456

queueName?: string;

457

once?: boolean;

458

run?: boolean;

459

edit?: boolean;

460

skip?: boolean;

461

args?: any[] | ((generator: Generator) => any[]);

462

reject?: (error: unknown) => void;

463

taskPrefix?: string;

464

auto?: boolean;

465

taskOrigin?: any;

466

cancellable?: boolean;

467

}

468

469

interface TaskOptions {

470

queueName?: string;

471

once?: boolean;

472

run?: boolean;

473

edit?: boolean;

474

skip?: boolean;

475

args?: any[] | ((generator: Generator) => any[]);

476

reject?: (error: unknown) => void;

477

taskPrefix?: string;

478

auto?: boolean;

479

taskOrigin?: any;

480

cancellable?: boolean;

481

}

482

483

interface Priority {

484

priorityName: string;

485

queueName?: string;

486

before?: string;

487

once?: boolean;

488

run?: boolean;

489

edit?: boolean;

490

skip?: boolean;

491

args?: any[] | ((generator: Generator) => any[]);

492

}

493

494

interface ComposeOptions<G extends BaseGenerator = BaseGenerator> {

495

generatorArgs?: string[];

496

generatorOptions?: Partial<GetGeneratorOptions<G>>;

497

destinationRoot?: string;

498

skipEnvRegister?: boolean;

499

forceResolve?: boolean;

500

forwardOptions?: boolean;

501

schedule?: boolean;

502

}

503

504

interface GeneratorPipelineOptions {

505

disabled?: boolean;

506

name?: string;

507

pendingFiles?: boolean;

508

filter?: (file: MemFsEditorFile) => boolean;

509

}

510

511

type TaskStatus = {

512

cancelled: boolean;

513

timestamp: Date;

514

};

515

```