0
# Task Classes
1
2
Direct access to Jake's task class hierarchy for programmatic task creation and advanced build system development. These classes provide the foundation for all task types in Jake.
3
4
## Capabilities
5
6
### Task Class
7
8
The base Task class that all Jake tasks inherit from. Extends EventEmitter for lifecycle events.
9
10
```javascript { .api }
11
/**
12
* Base Task class for all Jake tasks
13
*/
14
class Task extends EventEmitter {
15
constructor(name, prereqs, action, opts);
16
17
// Core properties
18
name: string; // Task name
19
prereqs: string[]; // Prerequisites to run before this task
20
action: Function; // Task action function
21
async: boolean; // Whether task runs asynchronously
22
taskStatus: string; // Current status (UNSTARTED/STARTED/DONE/ERROR)
23
description: string; // Task description for help
24
args: any[]; // Arguments passed to task
25
value: any; // Return value from task action
26
concurrency: number; // Concurrency level for prerequisites
27
startTime: number; // Task start timestamp
28
endTime: number; // Task completion timestamp
29
directory: string; // Directory to change to before running
30
namespace: Namespace; // Parent namespace
31
32
// Computed properties
33
get fullName(): string; // Full namespaced task name
34
get params(): string; // Formatted parameter list for display
35
36
// Core methods
37
invoke(...args: any[]): void; // Run prereqs then this task
38
execute(...args: any[]): void; // Run only this task (skip prereqs)
39
reenable(deep?: boolean): void; // Reset task to allow re-running
40
isNeeded(): boolean; // Check if task needs to run
41
complete(value?: any): void; // Mark task as complete
42
43
// Static properties
44
static runStatuses: {
45
UNSTARTED: string;
46
STARTED: string;
47
DONE: string;
48
ERROR: string;
49
};
50
51
// Static methods
52
static getBaseNamespacePath(fullName: string): string; // Extract namespace path
53
static getBaseTaskName(fullName: string): string; // Extract task name
54
}
55
```
56
57
**Task Events:**
58
59
```javascript { .api }
60
interface TaskEvents {
61
'start': () => void; // Task started running
62
'complete': (value: any) => void; // Task completed successfully
63
'skip': () => void; // Task was skipped
64
'error': (err: Error) => void; // Task failed with error
65
}
66
```
67
68
**Usage Examples:**
69
70
```javascript
71
// Create task programmatically
72
const myTask = new jake.Task('compile', ['clean'], function () {
73
console.log('Compiling...');
74
jake.exec(['tsc'], { printStdout: true });
75
});
76
77
// Add description and add to namespace
78
myTask.description = 'Compile TypeScript files';
79
jake.currentNamespace.addTask(myTask);
80
81
// Monitor task execution
82
myTask.on('start', function () {
83
console.log('Task started:', this.name);
84
});
85
86
myTask.on('complete', function (value) {
87
console.log('Task completed:', this.name, 'Result:', value);
88
});
89
90
myTask.on('error', function (err) {
91
console.error('Task failed:', this.name, err.message);
92
});
93
94
// Execute task
95
myTask.invoke();
96
97
// Re-enable task for multiple runs
98
myTask.reenable();
99
myTask.execute(); // Run again without prereqs
100
```
101
102
### FileTask Class
103
104
File-based tasks that automatically check modification times to determine if execution is needed.
105
106
```javascript { .api }
107
/**
108
* FileTask class for file-based tasks with modification time checking
109
*/
110
class FileTask extends Task {
111
constructor(name, prereqs, action, opts);
112
113
// Additional properties
114
dummy: boolean; // Whether this is a dummy file task
115
modTime: Date; // File modification time
116
117
// Overridden methods
118
isNeeded(): boolean; // Check if file needs rebuilding
119
updateModTime(): void; // Update modification time from filesystem
120
complete(value?: any): void; // Complete and update mod time
121
}
122
```
123
124
**Usage Examples:**
125
126
```javascript
127
// Create file task programmatically
128
const jsTask = new jake.FileTask('dist/app.js', ['src/app.js', 'src/utils.js'], function () {
129
console.log('Building JavaScript bundle...');
130
jake.exec(['webpack src/app.js dist/app.js'], function () {
131
complete();
132
});
133
}, { async: true });
134
135
jake.currentNamespace.addTask(jsTask);
136
137
// Check if file needs updating
138
if (jsTask.isNeeded()) {
139
console.log('File is out of date, will rebuild');
140
} else {
141
console.log('File is up to date');
142
}
143
144
// Monitor file modification time
145
console.log('Current mod time:', jsTask.modTime);
146
jsTask.updateModTime();
147
console.log('Updated mod time:', jsTask.modTime);
148
149
// Create dummy file task for existing files
150
const configTask = new jake.FileTask('config.json');
151
configTask.dummy = true;
152
configTask.updateModTime();
153
```
154
155
### DirectoryTask Class
156
157
Directory creation tasks that ensure directories exist for build outputs.
158
159
```javascript { .api }
160
/**
161
* DirectoryTask class for ensuring directories exist
162
*/
163
class DirectoryTask extends FileTask {
164
constructor(name, prereqs, action, opts);
165
166
// Inherits all FileTask properties and methods
167
// Default action creates the directory using jake.mkdirP
168
}
169
```
170
171
**Usage Examples:**
172
173
```javascript
174
// Create directory task programmatically
175
const distDir = new jake.DirectoryTask('dist');
176
jake.currentNamespace.addTask(distDir);
177
178
// Create nested directory task
179
const assetsDirs = new jake.DirectoryTask('dist/assets/images');
180
jake.currentNamespace.addTask(assetsDirs);
181
182
// Directory task with custom action
183
const buildDir = new jake.DirectoryTask('build', [], function () {
184
jake.mkdirP(this.name);
185
console.log('Created build directory with custom setup');
186
// Additional setup for build directory
187
jake.cpR('templates', 'build/templates');
188
});
189
190
// Use directory tasks as prerequisites
191
const bundleTask = new jake.FileTask('dist/bundle.js', ['dist', 'src/**/*.js'], function () {
192
// dist directory is guaranteed to exist
193
jake.exec(['browserify src/main.js -o dist/bundle.js']);
194
});
195
```
196
197
### PackageTask Class
198
199
Specialized task for creating distributable packages in various archive formats.
200
201
```javascript { .api }
202
/**
203
* PackageTask class for creating distributable packages
204
*/
205
class PackageTask {
206
constructor(name, version, prereqs, definition);
207
208
// Core properties
209
name: string; // Project name
210
version: string; // Project version
211
prereqs: string[]; // Prerequisites to run before packaging
212
packageDir: string; // Directory for package output (default: 'pkg')
213
packageFiles: FileList; // Files to include in package
214
215
// Archive format flags
216
needTar: boolean; // Create .tgz archive
217
needTarGz: boolean; // Create .tar.gz archive
218
needTarBz2: boolean; // Create .tar.bz2 archive
219
needJar: boolean; // Create .jar archive
220
needZip: boolean; // Create .zip archive
221
222
// Archive configuration
223
manifestFile: string; // JAR manifest file path
224
tarCommand: string; // Tar command (default: 'tar')
225
jarCommand: string; // Jar command (default: 'jar')
226
zipCommand: string; // Zip command (default: 'zip')
227
archiveNoBaseDir: boolean; // Archive contents without base directory
228
archiveChangeDir: string; // Directory to change to before archiving
229
archiveContentDir: string; // Specific content directory to archive
230
231
// Methods
232
packageName(): string; // Get package name (name-version)
233
packageDirPath(): string; // Get full path to package directory
234
}
235
```
236
237
**Usage Examples:**
238
239
```javascript
240
// Create package task programmatically
241
const pkg = new jake.PackageTask('myapp', '2.1.0', ['build', 'test'], function () {
242
this.packageFiles.include([
243
'dist/**',
244
'lib/**',
245
'package.json',
246
'README.md',
247
'LICENSE'
248
]);
249
this.packageFiles.exclude([
250
'dist/**/*.map',
251
'lib/**/*.test.js'
252
]);
253
254
this.needTarGz = true;
255
this.needZip = true;
256
this.packageDir = 'releases';
257
});
258
259
// Access package properties
260
console.log('Package name:', pkg.packageName()); // 'myapp-2.1.0'
261
console.log('Package directory:', pkg.packageDirPath()); // './releases'
262
263
// Package creates these tasks automatically:
264
// - package: Build complete package
265
// - repackage: Rebuild package
266
// - clobberPackage: Remove package directory
267
```
268
269
### PublishTask Class
270
271
Specialized task for version management and package publishing workflows.
272
273
```javascript { .api }
274
/**
275
* PublishTask class for version management and publishing
276
*/
277
class PublishTask {
278
constructor(name, prereqs, opts, definition);
279
280
// Core properties
281
name: string; // Project name
282
prereqs: string[]; // Prerequisites to run before publishing
283
packageFiles: FileList; // Files to include in package
284
publishCmd: string; // Publish command template
285
publishMessage: string; // Success message
286
gitCmd: string; // Git command
287
versionFiles: string[]; // Files to update with new version
288
scheduleDelay: number; // Delay before publish command
289
290
// Methods
291
createPublishCommand?(version: string): string[]; // Custom publish command generator
292
}
293
```
294
295
**Usage Examples:**
296
297
```javascript
298
// Create publish task programmatically
299
const pub = new jake.PublishTask('myapp', ['build', 'test'], {
300
publishCmd: 'npm publish --registry=https://registry.npmjs.org %filename',
301
publishMessage: 'Successfully published to npm!',
302
versionFiles: ['package.json', 'bower.json']
303
}, function () {
304
this.packageFiles.include([
305
'dist/**',
306
'lib/**',
307
'package.json',
308
'README.md'
309
]);
310
311
// Custom publish command
312
this.createPublishCommand = function (version) {
313
return [
314
'npm publish --tag=latest',
315
'git tag v' + version,
316
'git push origin v' + version
317
];
318
};
319
});
320
321
// Publish creates these tasks automatically:
322
// - publish: Create new version and release
323
// - publishExisting: Release existing version
324
// - version: Update version files and push to git
325
```
326
327
### TestTask Class
328
329
Specialized task for running test suites with setup/teardown support.
330
331
```javascript { .api }
332
/**
333
* TestTask class for running test suites
334
*/
335
class TestTask {
336
constructor(name, prereqs, definition);
337
338
// Properties
339
testName: string; // Name of test namespace and task (default: 'test')
340
testFiles: FileList; // List of test files to load
341
showDescription: boolean; // Show task in `jake -T` (default: true)
342
totalTests: number; // Total number of tests to run
343
executedTests: number; // Number of successfully executed tests
344
}
345
```
346
347
**Usage Examples:**
348
349
```javascript
350
// Create test task programmatically
351
const test = new jake.TestTask('myproject', ['build'], function () {
352
this.testName = 'spec';
353
this.testFiles.include([
354
'test/unit/**/*.js',
355
'test/integration/**/*.js'
356
]);
357
this.testFiles.exclude('test/**/*.helper.js');
358
this.showDescription = true;
359
});
360
361
// Access test statistics
362
console.log('Total tests:', test.totalTests);
363
console.log('Executed tests:', test.executedTests);
364
365
// Test creates these tasks automatically:
366
// - spec (or testName): Main test task
367
// - spec:run: Internal test execution task
368
```
369
370
## Advanced Class Usage Patterns
371
372
### Custom Task Types
373
374
```javascript
375
// Create custom task type by extending Task
376
class CompileTask extends jake.Task {
377
constructor(source, target, compiler, opts) {
378
const name = target;
379
const prereqs = [source];
380
const action = function () {
381
const cmd = `${compiler} ${source} -o ${target}`;
382
jake.exec([cmd], { printStdout: true });
383
};
384
385
super(name, prereqs, action, opts);
386
387
this.source = source;
388
this.target = target;
389
this.compiler = compiler;
390
}
391
392
isNeeded() {
393
// Custom logic for determining if compilation is needed
394
const fs = require('fs');
395
396
if (!fs.existsSync(this.target)) {
397
return true;
398
}
399
400
const sourceStat = fs.statSync(this.source);
401
const targetStat = fs.statSync(this.target);
402
403
return sourceStat.mtime > targetStat.mtime;
404
}
405
}
406
407
// Use custom task type
408
const tsTask = new CompileTask('src/app.ts', 'dist/app.js', 'tsc');
409
jake.currentNamespace.addTask(tsTask);
410
```
411
412
### Task Composition
413
414
```javascript
415
// Compose complex tasks from simpler ones
416
class BuildPipeline {
417
constructor(name, stages) {
418
this.name = name;
419
this.stages = stages;
420
this.tasks = [];
421
422
this.createTasks();
423
}
424
425
createTasks() {
426
const stageNames = [];
427
428
this.stages.forEach((stage, index) => {
429
const stageName = `${this.name}:${stage.name}`;
430
const prereqs = index > 0 ? [stageNames[index - 1]] : stage.prereqs || [];
431
432
const task = new jake.Task(stageName, prereqs, stage.action, stage.opts);
433
task.description = stage.description;
434
435
jake.currentNamespace.addTask(task);
436
this.tasks.push(task);
437
stageNames.push(stageName);
438
});
439
440
// Create main task that runs all stages
441
const mainTask = new jake.Task(this.name, [stageNames[stageNames.length - 1]], function () {
442
console.log(`${this.name} pipeline completed successfully`);
443
});
444
445
jake.currentNamespace.addTask(mainTask);
446
this.tasks.push(mainTask);
447
}
448
}
449
450
// Use build pipeline
451
const pipeline = new BuildPipeline('deploy', [
452
{
453
name: 'test',
454
description: 'Run all tests',
455
action: function () {
456
jake.exec(['npm test'], { printStdout: true });
457
}
458
},
459
{
460
name: 'build',
461
description: 'Build application',
462
action: function () {
463
jake.exec(['npm run build'], { printStdout: true });
464
}
465
},
466
{
467
name: 'package',
468
description: 'Create deployment package',
469
action: function () {
470
jake.exec(['tar -czf deploy.tar.gz dist/'], { printStdout: true });
471
}
472
},
473
{
474
name: 'upload',
475
description: 'Upload to server',
476
action: function () {
477
jake.exec(['scp deploy.tar.gz server:/tmp/'], { printStdout: true });
478
},
479
opts: { async: true }
480
}
481
]);
482
```
483
484
### Task Monitoring and Metrics
485
486
```javascript
487
// Task performance monitoring
488
class TaskMonitor {
489
constructor() {
490
this.metrics = {};
491
}
492
493
attachTo(task) {
494
task.on('start', () => {
495
this.metrics[task.name] = {
496
startTime: Date.now(),
497
name: task.name
498
};
499
});
500
501
task.on('complete', () => {
502
const metric = this.metrics[task.name];
503
if (metric) {
504
metric.endTime = Date.now();
505
metric.duration = metric.endTime - metric.startTime;
506
metric.status = 'completed';
507
}
508
});
509
510
task.on('error', (err) => {
511
const metric = this.metrics[task.name];
512
if (metric) {
513
metric.endTime = Date.now();
514
metric.duration = metric.endTime - metric.startTime;
515
metric.status = 'failed';
516
metric.error = err.message;
517
}
518
});
519
}
520
521
getReport() {
522
return Object.values(this.metrics).map(metric => ({
523
task: metric.name,
524
duration: metric.duration + 'ms',
525
status: metric.status,
526
error: metric.error
527
}));
528
}
529
}
530
531
// Use task monitor
532
const monitor = new TaskMonitor();
533
534
// Attach to all tasks
535
jake.parseAllTasks();
536
for (const taskName in jake.Task) {
537
monitor.attachTo(jake.Task[taskName]);
538
}
539
540
// Add reporting task
541
task('report', function () {
542
console.table(monitor.getReport());
543
});
544
```