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-organization.mddocs/

Task Organization

Organize tasks hierarchically using namespaces and create dynamic tasks using pattern-based rules for scalable build systems and complex project structures.

Capabilities

Namespace

Creates a namespace for logical grouping of tasks and prevents name collisions. Namespaces can be nested inside other namespaces.

/**
 * Creates a namespace for logical task grouping
 * @param {string} name - The name of the namespace
 * @param {Function} closure - The enclosing scope for the namespaced tasks
 * @returns {Namespace} The created namespace instance
 */
function namespace(name, closure);

Usage Examples:

// Basic namespace
namespace('doc', function () {
  desc('Generate documentation');
  task('generate', ['doc:clean'], function () {
    jake.exec(['jsdoc src -d docs'], { printStdout: true });
  });

  desc('Clean documentation directory');
  task('clean', function () {
    jake.rmRf('docs');
  });
});

// Run with: jake doc:generate or jake doc:clean

// Nested namespaces
namespace('build', function () {
  namespace('assets', function () {
    desc('Compile CSS');
    task('css', function () {
      jake.exec(['sass src/styles:dist/css'], { printStdout: true });
    });

    desc('Optimize images');
    task('images', function () {
      jake.exec(['imagemin src/images dist/images'], { printStdout: true });
    });
  });

  desc('Build JavaScript');
  task('js', function () {
    jake.exec(['webpack --mode=production'], { printStdout: true });
  });

  desc('Build all assets');
  task('all', ['assets:css', 'assets:images', 'js'], function () {
    console.log('All assets built successfully');
  });
});

// Run with: jake build:assets:css, jake build:all, etc.

// Cross-namespace dependencies
namespace('test', function () {
  desc('Run unit tests');
  task('unit', ['build:js'], function () {
    jake.exec(['mocha test/unit/**/*.js'], { printStdout: true });
  });
});

Rules

Creates pattern-based rules that can automatically generate tasks based on file patterns. Useful for build systems that need to handle many similar files.

/**
 * Creates a Jake Suffix Rule for pattern-based task generation
 * Arguments after pattern and source can be provided in any order and are parsed by type
 * @param {string} pattern - The target file pattern to match
 * @param {string} source - The source file pattern or function
 * @param {string[]} [prereqs] - Additional prerequisites for generated tasks (optional, any order)
 * @param {Function} [action] - The action to perform for matched tasks (optional, any order)
 * @param {Object} [opts] - Task options (optional, any order)
 * @param {boolean} [opts.async=false] - Perform tasks asynchronously
 * @returns {void}
 */
function rule(pattern, source, ...args);

Usage Examples:

// Simple suffix rule - compile .c files to .o files
desc('Compile C files');
rule('.o', '.c', function () {
  const cmd = `gcc -c ${this.source} -o ${this.name}`;
  jake.exec([cmd], { printStdout: true });
});

// Rule with prerequisites - arguments can be in any order after pattern/source
rule('.o', '.c', ['config.h'], {async: true}, function () {
  const cmd = `gcc -c ${this.source} -o ${this.name}`;
  jake.exec([cmd], function () {
    complete();
  }, { printStdout: true });
});

// Flexible argument order - these are all equivalent:
rule('.min.js', '.js', function () { /* action */ }, {async: true});
rule('.min.js', '.js', {async: true}, function () { /* action */ });
rule('.min.js', '.js', ['package.json'], function () { /* action */ });
rule('.min.js', '.js', function () { /* action */ }, ['package.json']);

// Pattern-based rules with % wildcards
rule('%.min.js', '%.js', function () {
  const cmd = `uglifyjs ${this.source} -o ${this.name}`;
  jake.exec([cmd], { printStdout: true });
});

rule('dist/%.css', 'src/%.scss', ['src/_variables.scss'], function () {
  const cmd = `sass ${this.source} ${this.name}`;
  jake.exec([cmd], { printStdout: true });
});

// Directory-specific patterns
rule('obj/%.o', 'src/%.c', {async: true}, function () {
  jake.mkdirP('obj'); // Ensure target directory exists
  const cmd = `gcc -c ${this.source} -o ${this.name}`;
  jake.exec([cmd], function () {
    complete();
  }, { printStdout: true });
});

// Complex pattern rules
rule('build/compressed/%.min.js', 'build/compiled/%.js', ['build/compiled'], function () {
  const cmd = `uglifyjs ${this.source} --compress --mangle -o ${this.name}`;
  jake.exec([cmd], { printStdout: true });
});

// Chain rules for multiple transformations
rule('%.pdf', '%.dvi', {async: true}, function () {
  const cmd = `dvipdfm ${this.source}`;
  jake.exec([cmd], function () {
    complete();
  }, { printStdout: true });
});

rule('%.dvi', '%.tex', {async: true}, function () {
  const cmd = `latex ${this.source}`;
  jake.exec([cmd], function () {
    complete();
  }, { printStdout: true });
});

// Now you can do: jake document.pdf
// This will: document.tex → document.dvi → document.pdf

Namespace Class

Direct access to the Namespace class for programmatic namespace manipulation.

/**
 * Namespace class for organizing tasks hierarchically
 */
class Namespace {
  constructor(name, parentNamespace);
  
  name: string;                           // Namespace name
  parentNamespace: Namespace | null;      // Parent namespace
  childNamespaces: Object;                // Child namespaces by name
  tasks: Object;                          // Tasks in this namespace by name
  rules: Object;                          // Rules in this namespace by pattern
  path: string;                           // Colon-separated path from root
  fullName: string;                       // Full namespaced name
  
  addTask(task: Task): void;              // Add task to namespace
  resolveTask(name: string): Task | null; // Find task by name
  resolveNamespace(name: string): Namespace | null; // Find child namespace
  matchRule(name: string): Rule | null;   // Find matching rule
  getPath(): string;                      // Get namespace path
  isRootNamespace(): boolean;             // Check if root namespace
}

/**
 * Root namespace class - singleton container for all tasks
 */
class RootNamespace extends Namespace {
  constructor();
}

Advanced Organization Patterns

Modular Build System

// Load tasks from separate files
const loadTasks = function (path) {
  const tasks = require(path);
  if (typeof tasks === 'function') {
    tasks(); // Execute task definitions
  }
};

// tasks/build.js
module.exports = function () {
  namespace('build', function () {
    desc('Build CSS');
    task('css', function () {
      jake.exec(['sass src:dist'], { printStdout: true });
    });

    desc('Build JavaScript');
    task('js', function () {
      jake.exec(['webpack'], { printStdout: true });
    });

    desc('Build all');
    task('all', ['css', 'js']);
  });
};

// tasks/test.js
module.exports = function () {
  namespace('test', function () {
    desc('Run unit tests');
    task('unit', ['build:all'], function () {
      jake.exec(['mocha test/unit'], { printStdout: true });
    });

    desc('Run integration tests');
    task('integration', ['build:all'], function () {
      jake.exec(['mocha test/integration'], { printStdout: true });
    });

    desc('Run all tests');
    task('all', ['unit', 'integration']);
  });
};

// Jakefile.js
loadTasks('./tasks/build');
loadTasks('./tasks/test');

desc('Complete build and test');
task('default', ['build:all', 'test:all']);

Environment-Specific Namespaces

const environments = ['development', 'staging', 'production'];

environments.forEach(function (env) {
  namespace(env, function () {
    desc(`Deploy to ${env}`);
    task('deploy', [`build:${env}`], function () {
      console.log(`Deploying to ${env} environment`);
      jake.exec([`deploy-script --env=${env}`], { printStdout: true });
    });

    desc(`Build for ${env}`);
    task('build', function () {
      process.env.NODE_ENV = env;
      jake.exec(['webpack'], { printStdout: true });
    });

    desc(`Test ${env} build`);
    task('test', [`build`], function () {
      jake.exec([`test-script --env=${env}`], { printStdout: true });
    });
  });
});

// Usage: jake production:deploy, jake development:test, etc.

Rule-Based Asset Pipeline

// Asset processing rules
namespace('assets', function () {
  // Compile SCSS to CSS
  rule('dist/css/%.css', 'src/scss/%.scss', ['src/scss/_variables.scss'], function () {
    jake.mkdirP('dist/css');
    const cmd = `sass ${this.source} ${this.name}`;
    jake.exec([cmd], { printStdout: true });
  });

  // Minify CSS
  rule('dist/css/%.min.css', 'dist/css/%.css', function () {
    const cmd = `cleancss ${this.source} -o ${this.name}`;
    jake.exec([cmd], { printStdout: true });
  });

  // Process JavaScript
  rule('dist/js/%.js', 'src/js/%.js', function () {
    jake.mkdirP('dist/js');
    const cmd = `babel ${this.source} -o ${this.name}`;
    jake.exec([cmd], { printStdout: true });
  });

  // Minify JavaScript
  rule('dist/js/%.min.js', 'dist/js/%.js', function () {
    const cmd = `uglifyjs ${this.source} -o ${this.name}`;
    jake.exec([cmd], { printStdout: true });
  });

  // Optimize images
  rule('dist/images/%.jpg', 'src/images/%.jpg', function () {
    jake.mkdirP('dist/images');
    const cmd = `imagemin ${this.source} --out-dir=dist/images`;
    jake.exec([cmd], { printStdout: true });
  });

  rule('dist/images/%.png', 'src/images/%.png', function () {
    jake.mkdirP('dist/images');
    const cmd = `imagemin ${this.source} --out-dir=dist/images`;
    jake.exec([cmd], { printStdout: true });
  });

  // Build all assets
  desc('Build all CSS files');
  task('css', function () {
    const fs = require('fs');
    const path = require('path');
    
    const scssFiles = fs.readdirSync('src/scss')
      .filter(f => f.endsWith('.scss') && !f.startsWith('_'))
      .map(f => `dist/css/${path.basename(f, '.scss')}.min.css`);
    
    scssFiles.forEach(cssFile => {
      jake.Task[cssFile] && jake.Task[cssFile].invoke();
    });
  });

  desc('Build all JavaScript files');
  task('js', function () {
    const fs = require('fs');
    const path = require('path');
    
    const jsFiles = fs.readdirSync('src/js')
      .filter(f => f.endsWith('.js'))
      .map(f => `dist/js/${path.basename(f, '.js')}.min.js`);
    
    jsFiles.forEach(jsFile => {
      jake.Task[jsFile] && jake.Task[jsFile].invoke();
    });
  });

  desc('Process all images');
  task('images', function () {
    const glob = require('glob');
    
    const imageFiles = glob.sync('src/images/**/*.{jpg,png}')
      .map(f => f.replace('src/', 'dist/'));
    
    imageFiles.forEach(imgFile => {
      jake.Task[imgFile] && jake.Task[imgFile].invoke();
    });
  });

  desc('Build all assets');
  task('all', ['css', 'js', 'images']);
});

Conditional Task Loading

// Load tasks based on environment or configuration
const config = require('./build.config.js');

if (config.features.includes('typescript')) {
  namespace('typescript', function () {
    desc('Compile TypeScript');
    task('compile', function () {
      jake.exec(['tsc'], { printStdout: true });
    });

    rule('dist/%.js', 'src/%.ts', function () {
      const cmd = `tsc ${this.source} --outDir dist`;
      jake.exec([cmd], { printStdout: true });
    });
  });
}

if (config.features.includes('docker')) {
  namespace('docker', function () {
    desc('Build Docker image');
    task('build', function () {
      jake.exec(['docker build -t myapp .'], { printStdout: true });
    });

    desc('Run Docker container');
    task('run', ['build'], function () {
      jake.exec(['docker run -p 3000:3000 myapp'], { printStdout: true });
    });
  });
}

docs

build-tasks.md

core-tasks.md

index.md

task-classes.md

task-organization.md

utilities.md

tile.json