• Stars
    star
    194
  • Rank 192,976 (Top 4 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 9 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Task registry that allows composition through series/parallel methods.

undertaker

NPM version Downloads Azure Pipelines Build Status Travis Build Status AppVeyor Build Status Coveralls Status Gitter chat

Usage

var fs = require('fs');
var Undertaker = require('undertaker');

var taker = new Undertaker();

taker.task('task1', function(cb){
  // do things

  cb(); // when everything is done
});

taker.task('task2', function(){
  return fs.createReadStream('./myFile.js')
    .pipe(fs.createWriteStream('./myFile.copy.js'));
});

taker.task('task3', function(){
  return new Promise(function(resolve, reject){
    // do things

    resolve(); // when everything is done
  });
});

taker.task('combined', taker.series('task1', 'task2'));

taker.task('all', taker.parallel('combined', 'task3'));

API

Task functions can be completed in any of the ways supported by async-done

new Undertaker([registryInstance])

The constructor is used to create a new instance of Undertaker. Each instance of Undertaker gets its own instance of a registry. By default, the registry is an instance of undertaker-registry but it can be an instance of any other registry that follows the Custom Registries API.

To use a custom registry, pass a custom registry instance (new CustomRegistry([options])) when instantiating a new Undertaker instance. This will use the custom registry instance for that Undertaker instance.

task([taskName,] fn)

Both a getter and setter for tasks.

If a string (taskName) is given as the only argument, it behaves as a getter and returns the wrapped task (not the original function). The wrapped task has a unwrap method that will return the original function.

If a function (fn) and optionally a string (taskName) is given, it behaves as a setter and will register the task by the taskName. If taskName is not specified, the name or displayName property of the function is used as the taskName.

Will throw if:

  • As a getter: taskName is missing or not a string.
  • As a setter: taskName is missing and fn is anonymous.
  • As a setter: fn is missing or not a function.

series(taskName || fn...)

Takes a variable amount of strings (taskName) and/or functions (fn) and returns a function of the composed tasks or functions. Any taskNames are retrieved from the registry using the get method.

When the returned function is executed, the tasks or functions will be executed in series, each waiting for the prior to finish. If an error occurs, execution will stop.

parallel(taskName || fn...)

Takes a variable amount of strings (taskName) and/or functions (fn) and returns a function of the composed tasks or functions. Any taskNames are retrieved from the registry using the get method.

When the returned function is executed, the tasks or functions will be executed in parallel, all being executed at the same time. If an error occurs, all execution will complete.

registry([registryInstance])

Optionally takes an instantiated registry object. If no arguments are passed, returns the current registry object. If an instance of a registry (customRegistry) is passed the tasks from the current registry will be transferred to it and the current registry will be replaced with the new registry.

The ability to assign new registries will allow you to pre-define/share tasks or add custom functionality to your registries. See Custom Registries for more information.

tree([options])

Optionally takes an options object and returns an object representing the tree of registered tasks. The object returned is archy compatible. Also, each node has a type property that can be used to determine if the node is a task or function.

options

options.deep

Whether or not the whole tree should be returned.

Type: Boolean

Default: false

lastRun(task, [precision])

Takes a string or function (task) and returns a timestamp of the last time the task was run successfully. The time will be the time the task started.

Returns undefined if the task has not been run.

If a task errors, the result of lastRun will be undefined because the task should probably be re-run from scratch to get into a good state again.

The timestamp is always given in millisecond but the time resolution can be rounded using the precision parameter. The use case is to be able to compare a build time to a file time attribute. On node v0.10 or with file system like HFS or FAT, fs.stat time attributes like mtime precision is one second.

Assuming undertakerInst.lastRun('someTask') returns 1426000001111, undertakerInst.lastRun('someTask', 1000) returns 1426000001000.

The default time resolution is 1000 on node v0.10, 0 on node 0.11+ but it can be overwritten using UNDERTAKER_TIME_RESOLUTION environment variable.

Custom Registries

Custom registries are constructor functions allowing you to pre-define/share tasks or add custom functionality to your registries.

A registry's prototype should define:

  • init(taker): receives the undertaker instance to set pre-defined tasks using the task(taskName, fn) method.
  • get(taskName): returns the task with that name or undefined if no task is registered with that name.
  • set(taskName, fn): add task to the registry. If set modifies a task, it should return the new task.
  • tasks(): returns an object listing all tasks in the registry.

You should not call these functions yourself; leave that to Undertaker, so it can keep its metadata consistent.

The easiest way to create a custom registry is to inherit from undertaker-registry:

var util = require('util');

var DefaultRegistry = require('undertaker-registry');

function MyRegistry(){
  DefaultRegistry.call(this);
}

util.inherits(MyRegistry, DefaultRegistry);

module.exports = MyRegistry;

Sharing tasks

To share common tasks with all your projects, you can expose an init method on the registry prototype and it will receive the Undertaker instance as the only argument. You can then use undertaker.task(name, fn) to register pre-defined tasks.

For example you might want to share a clean task:

var fs = require('fs');
var util = require('util');

var DefaultRegistry = require('undertaker-registry');
var del = require('del');

function CommonRegistry(opts){
  DefaultRegistry.call(this);

  opts = opts || {};

  this.buildDir = opts.buildDir || './build';
}

util.inherits(CommonRegistry, DefaultRegistry);

CommonRegistry.prototype.init = function(takerInst){
  var buildDir = this.buildDir;
  var exists = fs.existsSync(buildDir);

  if(exists){
    throw new Error('Cannot initialize common tasks. ' + buildDir + ' directory exists.');
  }

  takerInst.task('clean', function(){
    return del([buildDir]);
  });
}

module.exports = CommonRegistry;

Then to use it in a project:

var Undertaker = require('undertaker');
var CommonRegistry = require('myorg-common-tasks');

var taker = new Undertaker(CommonRegistry({ buildDir: '/dist' }));

taker.task('build', taker.series('clean', function build(cb) {
  // do things
  cb();
}));

Sharing Functionalities

By controlling how tasks are added to the registry, you can decorate them.

For example if you wanted all tasks to share some data, you can use a custom registry to bind them to that data. Be sure to return the altered task, as per the description of registry methods above:

var util = require('util');

var Undertaker = require('undertaker');
var DefaultRegistry = require('undertaker-registry');

// Some task defined somewhere else
var BuildRegistry = require('./build.js');
var ServeRegistry = require('./serve.js');

function ConfigRegistry(config){
  DefaultRegistry.call(this);
  this.config = config;
}

util.inherits(ConfigRegistry, DefaultRegistry);

ConfigRegistry.prototype.set = function set(name, fn) {
  // The `DefaultRegistry` uses `this._tasks` for storage.
  var task = this._tasks[name] = fn.bind(this.config);
  return task;
};

var taker = new Undertaker();

taker.registry(new BuildRegistry());
taker.registry(new ServeRegistry());

// `taker.registry` will reset each task in the registry with
// `ConfigRegistry.prototype.set` which will bind them to the config object.
taker.registry(new ConfigRegistry({
  src: './src',
  build: './build',
  bindTo: '0.0.0.0:8888'
}));

taker.task('default', taker.series('clean', 'build', 'serve', function(cb) {
  console.log('Server bind to ' + this.bindTo);
  console.log('Serving' + this.build);
  cb();
}));

In the wild

License

MIT

More Repositories

1

gulp

A toolkit to automate & enhance your workflow
JavaScript
32,856
star
2

vinyl

Virtual file format.
JavaScript
1,261
star
3

vinyl-fs

Vinyl adapter for the file system.
JavaScript
963
star
4

liftoff

Launch your command line tool with ease.
JavaScript
836
star
5

gulp-util

[deprecated] - See https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5
JavaScript
830
star
6

gulp-cli

Command Line Interface for gulp.
JavaScript
392
star
7

plugins

[Unused] Very old plugin search website
JavaScript
280
star
8

interpret

A dictionary of file extensions and associated module loaders.
JavaScript
254
star
9

glob-stream

Readable streamx interface over anymatch.
JavaScript
178
star
10

bach

Compose your async functions with elegance.
JavaScript
132
star
11

fancy-log

Log things, prefixed with a timestamp.
JavaScript
119
star
12

findup-sync

Find the first file matching a given pattern in the current directory or the nearest ancestor directory.
JavaScript
97
star
13

glob-watcher

Watch globs and execute a function upon change, with intelligent defaults for debouncing and queueing.
JavaScript
79
star
14

glob-parent

Extract the non-magic parent path from a glob string.
JavaScript
76
star
15

async-done

Allows libraries to handle various caller provided asynchronous functions uniformly. Maps promises, observables, child processes and streams, and callbacks to callback style.
JavaScript
69
star
16

v8flags

Get available v8 and Node.js flags.
JavaScript
56
star
17

gulplog

Logger for gulp and gulp plugins
JavaScript
56
star
18

rechoir

Prepare a node environment to require files with different extensions.
JavaScript
47
star
19

replace-ext

Replaces a file extension with another one.
JavaScript
46
star
20

gulpjs.github.io

The gulp website
JavaScript
45
star
21

ordered-read-streams

Combines array of streams into one Readable stream in strict order.
JavaScript
28
star
22

now-and-later

Map over an array or object of values in parallel or series, passing each through the async iterator, with optional lifecycle hooks.
JavaScript
24
star
23

hacker

Hack on your project easily. A liftoff proof-of-concept.
JavaScript
23
star
24

flagged-respawn

A tool for respawning node binaries when special flags are present.
JavaScript
21
star
25

artwork

Artwork for the gulp project
21
star
26

plugin-error

Error handling for vinyl plugins. Just an abstraction of what's in gulp-util with minor reformatting.
JavaScript
21
star
27

empty-dir

Check if a directory is empty.
JavaScript
20
star
28

sparkles

Namespaced global event emitter
JavaScript
20
star
29

acceptance

Acceptance test suite for plugins
19
star
30

undertaker-forward-reference

Undertaker custom registry supporting forward referenced tasks.
JavaScript
19
star
31

glogg

Global logging utility.
JavaScript
18
star
32

lead

Sink your streams.
JavaScript
17
star
33

undertaker-registry

Default registry in gulp 4.
JavaScript
17
star
34

vinyl-sourcemap

Add/write sourcemaps to/from Vinyl files.
JavaScript
15
star
35

last-run

Capture and retrieve the last time a function was run
JavaScript
14
star
36

path-dirname

Node.js path.dirname() ponyfill
JavaScript
13
star
37

fined

Find a file given a declaration of locations.
JavaScript
12
star
38

async-settle

Settle an async function. It will always complete successfully with an object of the resulting state.
JavaScript
11
star
39

value-or-function

Normalize a value or function, applying extra args to the function
JavaScript
11
star
40

copy-props

Copy properties deeply between two objects
JavaScript
10
star
41

to-through

Wrap a Readable stream in a Transform stream.
JavaScript
10
star
42

semver-greatest-satisfied-range

Find the greatest satisfied semver range from an array of ranges.
JavaScript
9
star
43

mute-stdout

Mute and unmute stdout
JavaScript
9
star
44

resolve-options

Resolve an options object based on configuration.
JavaScript
9
star
45

has-gulplog

Check if gulplog is available before attempting to use it
JavaScript
9
star
46

clone-buffer

Easier Buffer cloning in node.
JavaScript
9
star
47

eslint-config-gulp

Sharable eslint config for gulp projects
JavaScript
8
star
48

async-once

Guarantee a node-style async function is only executed once.
JavaScript
8
star
49

fs-mkdirp-stream

Ensure directories exist before writing to them.
JavaScript
8
star
50

undertaker-common-tasks

Proof-of-concept custom registry that pre-defines tasks.
JavaScript
7
star
51

remove-bom-stream

Remove a UTF8 BOM at the start of the stream.
JavaScript
7
star
52

registry

[Unused] NPM on ElasticSearch
JavaScript
5
star
53

better-stats

A replacement for node's fs.Stats with more utility
JavaScript
5
star
54

theming-log

Creates a logger with theme for text decoration.
JavaScript
4
star
55

undertaker-task-metadata

Proof-of-concept custom registry that attaches metadata to each task.
JavaScript
4
star
56

vinyl-contents

Utility to read the contents of a vinyl file.
JavaScript
4
star
57

replace-homedir

Replace user home in a string with another string. Useful for tildifying a path.
JavaScript
4
star
58

each-props

Process object properties deeply.
JavaScript
3
star
59

evented-require

Require modules and receive events.
JavaScript
3
star
60

update-template

Updates a gulpjs repository to match our current scaffold.
JavaScript
3
star
61

.github

GitHub template files for the gulpjs organization.
3
star
62

vinyl-prepare

[deprecated] This module's API was never satisfactory and isn't used in gulp - please don't use.
JavaScript
3
star
63

.boilerplate

The boilerplate template for gulp packages.
3
star
64

parse-node-version

Turn node's process.version into something useful.
JavaScript
2
star
65

default-resolution

Get the default resolution time based on the current node version, optionally overridable
JavaScript
2
star
66

jscs-preset-gulp

Sharable jscs config for gulp projects
2
star
67

conventional-changelog-gulp

conventional-changelog gulp preset
JavaScript
1
star
68

emit-mapper

Re-emit events while mapping them to new names.
JavaScript
1
star