CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jake

JavaScript build tool, similar to Make or Rake

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

task-classes.mddocs/

Task Classes

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.

Capabilities

Task Class

The base Task class that all Jake tasks inherit from. Extends EventEmitter for lifecycle events.

/**
 * Base Task class for all Jake tasks
 */
class Task extends EventEmitter {
  constructor(name, prereqs, action, opts);
  
  // Core properties
  name: string;                    // Task name
  prereqs: string[];              // Prerequisites to run before this task
  action: Function;               // Task action function
  async: boolean;                 // Whether task runs asynchronously
  taskStatus: string;             // Current status (UNSTARTED/STARTED/DONE/ERROR)
  description: string;            // Task description for help
  args: any[];                    // Arguments passed to task
  value: any;                     // Return value from task action
  concurrency: number;            // Concurrency level for prerequisites
  startTime: number;              // Task start timestamp
  endTime: number;                // Task completion timestamp
  directory: string;              // Directory to change to before running
  namespace: Namespace;           // Parent namespace
  
  // Computed properties
  get fullName(): string;         // Full namespaced task name
  get params(): string;           // Formatted parameter list for display
  
  // Core methods
  invoke(...args: any[]): void;           // Run prereqs then this task
  execute(...args: any[]): void;          // Run only this task (skip prereqs)
  reenable(deep?: boolean): void;         // Reset task to allow re-running
  isNeeded(): boolean;                    // Check if task needs to run
  complete(value?: any): void;            // Mark task as complete
  
  // Static properties
  static runStatuses: {
    UNSTARTED: string;
    STARTED: string;
    DONE: string;
    ERROR: string;
  };
  
  // Static methods
  static getBaseNamespacePath(fullName: string): string;  // Extract namespace path
  static getBaseTaskName(fullName: string): string;       // Extract task name
}

Task Events:

interface TaskEvents {
  'start': () => void;                    // Task started running
  'complete': (value: any) => void;       // Task completed successfully
  'skip': () => void;                     // Task was skipped
  'error': (err: Error) => void;          // Task failed with error
}

Usage Examples:

// Create task programmatically
const myTask = new jake.Task('compile', ['clean'], function () {
  console.log('Compiling...');
  jake.exec(['tsc'], { printStdout: true });
});

// Add description and add to namespace
myTask.description = 'Compile TypeScript files';
jake.currentNamespace.addTask(myTask);

// Monitor task execution
myTask.on('start', function () {
  console.log('Task started:', this.name);
});

myTask.on('complete', function (value) {
  console.log('Task completed:', this.name, 'Result:', value);
});

myTask.on('error', function (err) {
  console.error('Task failed:', this.name, err.message);
});

// Execute task
myTask.invoke();

// Re-enable task for multiple runs
myTask.reenable();
myTask.execute(); // Run again without prereqs

FileTask Class

File-based tasks that automatically check modification times to determine if execution is needed.

/**
 * FileTask class for file-based tasks with modification time checking
 */
class FileTask extends Task {
  constructor(name, prereqs, action, opts);
  
  // Additional properties
  dummy: boolean;                 // Whether this is a dummy file task
  modTime: Date;                  // File modification time
  
  // Overridden methods
  isNeeded(): boolean;            // Check if file needs rebuilding
  updateModTime(): void;          // Update modification time from filesystem
  complete(value?: any): void;    // Complete and update mod time
}

Usage Examples:

// Create file task programmatically
const jsTask = new jake.FileTask('dist/app.js', ['src/app.js', 'src/utils.js'], function () {
  console.log('Building JavaScript bundle...');
  jake.exec(['webpack src/app.js dist/app.js'], function () {
    complete();
  });
}, { async: true });

jake.currentNamespace.addTask(jsTask);

// Check if file needs updating
if (jsTask.isNeeded()) {
  console.log('File is out of date, will rebuild');
} else {
  console.log('File is up to date');
}

// Monitor file modification time
console.log('Current mod time:', jsTask.modTime);
jsTask.updateModTime();
console.log('Updated mod time:', jsTask.modTime);

// Create dummy file task for existing files
const configTask = new jake.FileTask('config.json');
configTask.dummy = true;
configTask.updateModTime();

DirectoryTask Class

Directory creation tasks that ensure directories exist for build outputs.

/**
 * DirectoryTask class for ensuring directories exist
 */
class DirectoryTask extends FileTask {
  constructor(name, prereqs, action, opts);
  
  // Inherits all FileTask properties and methods
  // Default action creates the directory using jake.mkdirP
}

Usage Examples:

// Create directory task programmatically
const distDir = new jake.DirectoryTask('dist');
jake.currentNamespace.addTask(distDir);

// Create nested directory task
const assetsDirs = new jake.DirectoryTask('dist/assets/images');
jake.currentNamespace.addTask(assetsDirs);

// Directory task with custom action
const buildDir = new jake.DirectoryTask('build', [], function () {
  jake.mkdirP(this.name);
  console.log('Created build directory with custom setup');
  // Additional setup for build directory
  jake.cpR('templates', 'build/templates');
});

// Use directory tasks as prerequisites
const bundleTask = new jake.FileTask('dist/bundle.js', ['dist', 'src/**/*.js'], function () {
  // dist directory is guaranteed to exist
  jake.exec(['browserify src/main.js -o dist/bundle.js']);
});

PackageTask Class

Specialized task for creating distributable packages in various archive formats.

/**
 * PackageTask class for creating distributable packages
 */
class PackageTask {
  constructor(name, version, prereqs, definition);
  
  // Core properties
  name: string;                    // Project name
  version: string;                 // Project version
  prereqs: string[];              // Prerequisites to run before packaging
  packageDir: string;             // Directory for package output (default: 'pkg')
  packageFiles: FileList;         // Files to include in package
  
  // Archive format flags
  needTar: boolean;               // Create .tgz archive
  needTarGz: boolean;             // Create .tar.gz archive
  needTarBz2: boolean;            // Create .tar.bz2 archive
  needJar: boolean;               // Create .jar archive
  needZip: boolean;               // Create .zip archive
  
  // Archive configuration
  manifestFile: string;           // JAR manifest file path
  tarCommand: string;             // Tar command (default: 'tar')
  jarCommand: string;             // Jar command (default: 'jar')
  zipCommand: string;             // Zip command (default: 'zip')
  archiveNoBaseDir: boolean;      // Archive contents without base directory
  archiveChangeDir: string;       // Directory to change to before archiving
  archiveContentDir: string;      // Specific content directory to archive
  
  // Methods
  packageName(): string;          // Get package name (name-version)
  packageDirPath(): string;       // Get full path to package directory
}

Usage Examples:

// Create package task programmatically
const pkg = new jake.PackageTask('myapp', '2.1.0', ['build', 'test'], function () {
  this.packageFiles.include([
    'dist/**',
    'lib/**',
    'package.json',
    'README.md',
    'LICENSE'
  ]);
  this.packageFiles.exclude([
    'dist/**/*.map',
    'lib/**/*.test.js'
  ]);
  
  this.needTarGz = true;
  this.needZip = true;
  this.packageDir = 'releases';
});

// Access package properties
console.log('Package name:', pkg.packageName()); // 'myapp-2.1.0'
console.log('Package directory:', pkg.packageDirPath()); // './releases'

// Package creates these tasks automatically:
// - package: Build complete package
// - repackage: Rebuild package
// - clobberPackage: Remove package directory

PublishTask Class

Specialized task for version management and package publishing workflows.

/**
 * PublishTask class for version management and publishing
 */
class PublishTask {
  constructor(name, prereqs, opts, definition);
  
  // Core properties
  name: string;                    // Project name
  prereqs: string[];              // Prerequisites to run before publishing
  packageFiles: FileList;         // Files to include in package
  publishCmd: string;             // Publish command template
  publishMessage: string;         // Success message
  gitCmd: string;                 // Git command
  versionFiles: string[];         // Files to update with new version
  scheduleDelay: number;          // Delay before publish command
  
  // Methods
  createPublishCommand?(version: string): string[]; // Custom publish command generator
}

Usage Examples:

// Create publish task programmatically
const pub = new jake.PublishTask('myapp', ['build', 'test'], {
  publishCmd: 'npm publish --registry=https://registry.npmjs.org %filename',
  publishMessage: 'Successfully published to npm!',
  versionFiles: ['package.json', 'bower.json']
}, function () {
  this.packageFiles.include([
    'dist/**',
    'lib/**',
    'package.json',
    'README.md'
  ]);
  
  // Custom publish command
  this.createPublishCommand = function (version) {
    return [
      'npm publish --tag=latest',
      'git tag v' + version,
      'git push origin v' + version
    ];
  };
});

// Publish creates these tasks automatically:
// - publish: Create new version and release
// - publishExisting: Release existing version
// - version: Update version files and push to git

TestTask Class

Specialized task for running test suites with setup/teardown support.

/**
 * TestTask class for running test suites
 */
class TestTask {
  constructor(name, prereqs, definition);
  
  // Properties
  testName: string;               // Name of test namespace and task (default: 'test')
  testFiles: FileList;           // List of test files to load
  showDescription: boolean;       // Show task in `jake -T` (default: true)
  totalTests: number;            // Total number of tests to run
  executedTests: number;         // Number of successfully executed tests
}

Usage Examples:

// Create test task programmatically
const test = new jake.TestTask('myproject', ['build'], function () {
  this.testName = 'spec';
  this.testFiles.include([
    'test/unit/**/*.js',
    'test/integration/**/*.js'
  ]);
  this.testFiles.exclude('test/**/*.helper.js');
  this.showDescription = true;
});

// Access test statistics
console.log('Total tests:', test.totalTests);
console.log('Executed tests:', test.executedTests);

// Test creates these tasks automatically:
// - spec (or testName): Main test task
// - spec:run: Internal test execution task

Advanced Class Usage Patterns

Custom Task Types

// Create custom task type by extending Task
class CompileTask extends jake.Task {
  constructor(source, target, compiler, opts) {
    const name = target;
    const prereqs = [source];
    const action = function () {
      const cmd = `${compiler} ${source} -o ${target}`;
      jake.exec([cmd], { printStdout: true });
    };
    
    super(name, prereqs, action, opts);
    
    this.source = source;
    this.target = target;
    this.compiler = compiler;
  }
  
  isNeeded() {
    // Custom logic for determining if compilation is needed
    const fs = require('fs');
    
    if (!fs.existsSync(this.target)) {
      return true;
    }
    
    const sourceStat = fs.statSync(this.source);
    const targetStat = fs.statSync(this.target);
    
    return sourceStat.mtime > targetStat.mtime;
  }
}

// Use custom task type
const tsTask = new CompileTask('src/app.ts', 'dist/app.js', 'tsc');
jake.currentNamespace.addTask(tsTask);

Task Composition

// Compose complex tasks from simpler ones
class BuildPipeline {
  constructor(name, stages) {
    this.name = name;
    this.stages = stages;
    this.tasks = [];
    
    this.createTasks();
  }
  
  createTasks() {
    const stageNames = [];
    
    this.stages.forEach((stage, index) => {
      const stageName = `${this.name}:${stage.name}`;
      const prereqs = index > 0 ? [stageNames[index - 1]] : stage.prereqs || [];
      
      const task = new jake.Task(stageName, prereqs, stage.action, stage.opts);
      task.description = stage.description;
      
      jake.currentNamespace.addTask(task);
      this.tasks.push(task);
      stageNames.push(stageName);
    });
    
    // Create main task that runs all stages
    const mainTask = new jake.Task(this.name, [stageNames[stageNames.length - 1]], function () {
      console.log(`${this.name} pipeline completed successfully`);
    });
    
    jake.currentNamespace.addTask(mainTask);
    this.tasks.push(mainTask);
  }
}

// Use build pipeline
const pipeline = new BuildPipeline('deploy', [
  {
    name: 'test',
    description: 'Run all tests',
    action: function () {
      jake.exec(['npm test'], { printStdout: true });
    }
  },
  {
    name: 'build',
    description: 'Build application',
    action: function () {
      jake.exec(['npm run build'], { printStdout: true });
    }
  },
  {
    name: 'package',
    description: 'Create deployment package',
    action: function () {
      jake.exec(['tar -czf deploy.tar.gz dist/'], { printStdout: true });
    }
  },
  {
    name: 'upload',
    description: 'Upload to server',
    action: function () {
      jake.exec(['scp deploy.tar.gz server:/tmp/'], { printStdout: true });
    },
    opts: { async: true }
  }
]);

Task Monitoring and Metrics

// Task performance monitoring
class TaskMonitor {
  constructor() {
    this.metrics = {};
  }
  
  attachTo(task) {
    task.on('start', () => {
      this.metrics[task.name] = {
        startTime: Date.now(),
        name: task.name
      };
    });
    
    task.on('complete', () => {
      const metric = this.metrics[task.name];
      if (metric) {
        metric.endTime = Date.now();
        metric.duration = metric.endTime - metric.startTime;
        metric.status = 'completed';
      }
    });
    
    task.on('error', (err) => {
      const metric = this.metrics[task.name];
      if (metric) {
        metric.endTime = Date.now();
        metric.duration = metric.endTime - metric.startTime;
        metric.status = 'failed';
        metric.error = err.message;
      }
    });
  }
  
  getReport() {
    return Object.values(this.metrics).map(metric => ({
      task: metric.name,
      duration: metric.duration + 'ms',
      status: metric.status,
      error: metric.error
    }));
  }
}

// Use task monitor
const monitor = new TaskMonitor();

// Attach to all tasks
jake.parseAllTasks();
for (const taskName in jake.Task) {
  monitor.attachTo(jake.Task[taskName]);
}

// Add reporting task
task('report', function () {
  console.table(monitor.getReport());
});

docs

build-tasks.md

core-tasks.md

index.md

task-classes.md

task-organization.md

utilities.md

tile.json