Skip to content

Commit 21a301c

Browse files
committed
New: First implementation
1 parent 51b56e6 commit 21a301c

10 files changed

+481
-0
lines changed

.travis.yml

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
language: node_js
2+
node_js:
3+
- '0.10'

index.js

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
'use strict';
2+
3+
var inherits = require('util').inherits;
4+
var EventEmitter = require('events').EventEmitter;
5+
6+
var bach = require('bach');
7+
var DefaultRegistry = require('undertaker-registry');
8+
9+
var metadata = require('./lib/metadata');
10+
var normalizeArgs = require('./lib/normalizeArgs');
11+
var createExtensions = require('./lib/createExtensions');
12+
13+
function Undertaker(Registry){
14+
EventEmitter.call(this);
15+
16+
Registry = Registry || DefaultRegistry;
17+
18+
this.registry = new Registry();
19+
}
20+
21+
inherits(Undertaker, EventEmitter);
22+
23+
Undertaker.prototype.get = function get(name){
24+
var wrapper = this.registry.get(name);
25+
26+
if(!wrapper){
27+
return;
28+
}
29+
30+
var meta = metadata.get(wrapper);
31+
32+
if(meta){
33+
return meta.orig;
34+
}
35+
36+
return wrapper;
37+
};
38+
39+
Undertaker.prototype.set = function set(name, fn){
40+
function taskWrapper(){
41+
/* jshint validthis: true */
42+
return fn.apply(this, arguments);
43+
}
44+
45+
metadata.set(taskWrapper, {
46+
name: name,
47+
orig: fn
48+
});
49+
50+
this.registry.set(name, taskWrapper);
51+
};
52+
53+
Undertaker.prototype.task = function task(name, fn){
54+
if(typeof name === 'function'){
55+
fn = name;
56+
name = fn.name;
57+
}
58+
59+
if(!fn){
60+
return this.get(name);
61+
}
62+
63+
this.set(name, fn);
64+
};
65+
66+
Undertaker.prototype.series = function series(){
67+
var args = normalizeArgs(this.registry, arguments);
68+
var extensions = createExtensions(this);
69+
var fn = bach.series(args, extensions);
70+
metadata.set(fn, { name: 'series' });
71+
return fn;
72+
};
73+
74+
Undertaker.prototype.parallel = function parallel(){
75+
var args = normalizeArgs(this.registry, arguments);
76+
var extensions = createExtensions(this);
77+
var fn = bach.parallel(args, extensions);
78+
metadata.set(fn, { name: 'parallel' });
79+
return fn;
80+
};
81+
82+
module.exports = Undertaker;

lib/createExtensions.js

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
'use strict';
2+
3+
var uid = 0;
4+
5+
var metadata = require('./metadata');
6+
7+
function Storage(name){
8+
this.uid = uid++;
9+
this.name = name;
10+
}
11+
12+
function createExtensions(ee){
13+
return {
14+
create: function(fn){
15+
var meta = metadata.get(fn);
16+
var name;
17+
18+
if(meta){
19+
name = meta.name;
20+
} else {
21+
name = fn.name;
22+
}
23+
24+
return new Storage(name);
25+
},
26+
before: function(storage){
27+
storage.startHr = process.hrtime();
28+
ee.emit('start', {
29+
uid: storage.uid,
30+
name: storage.name,
31+
time: Date.now()
32+
});
33+
},
34+
after: function(storage){
35+
ee.emit('stop', {
36+
uid: storage.uid,
37+
name: storage.name,
38+
duration: process.hrtime(storage.startHr),
39+
time: Date.now()
40+
});
41+
},
42+
error: function(storage){
43+
ee.emit('error', {
44+
uid: storage.uid,
45+
name: storage.name,
46+
duration: process.hrtime(storage.startHr),
47+
time: Date.now()
48+
});
49+
}
50+
};
51+
}
52+
53+
module.exports = createExtensions;

lib/metadata.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
3+
var WM = require('es6-weak-map');
4+
5+
// WeakMap for storing metadata
6+
var metadata = new WM();
7+
8+
module.exports = metadata;

lib/normalizeArgs.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
var assert = require('assert');
4+
5+
var _ = require('lodash');
6+
7+
function normalizeArgs(registry, args){
8+
function getFunction(task){
9+
if(typeof task === 'function'){
10+
return task;
11+
}
12+
13+
var fn = registry.get(task);
14+
assert(fn, 'Task never defined: ' + task);
15+
return fn;
16+
}
17+
18+
return _.map(_.flatten(args), getFunction);
19+
}
20+
21+
module.exports = normalizeArgs;

package.json

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "undertaker",
3+
"version": "0.0.0",
4+
"description": "undertaker ==========",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "lab -cv"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/phated/undertaker"
12+
},
13+
"keywords": [
14+
"task",
15+
"registry",
16+
"runner"
17+
],
18+
"author": "Blaine Bublitz <[email protected]> (http://iceddev.com/)",
19+
"license": "MIT",
20+
"bugs": {
21+
"url": "https://github.com/phated/undertaker/issues"
22+
},
23+
"homepage": "https://github.com/phated/undertaker",
24+
"devDependencies": {
25+
"lab": "^4.1.0"
26+
},
27+
"dependencies": {
28+
"bach": "^0.2.0",
29+
"es6-weak-map": "^0.1.1",
30+
"lodash": "^2.4.1",
31+
"undertaker-registry": "0.0.0"
32+
}
33+
}

test/parallel.js

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
'use strict';
2+
3+
var lab = exports.lab = require('lab').script();
4+
var describe = lab.describe;
5+
var it = lab.it;
6+
var before = lab.before;
7+
var beforeEach = lab.beforeEach;
8+
var after = lab.after;
9+
var afterEach = lab.afterEach;
10+
var expect = require('lab').expect;
11+
12+
var Undertaker = require('../');
13+
14+
function fn1(done){
15+
done(null, 1);
16+
}
17+
18+
function fn2(done){
19+
setTimeout(function(){
20+
done(null, 2);
21+
}, 500);
22+
}
23+
24+
function fn3(done){
25+
done(null, 3);
26+
}
27+
28+
function fnError(done){
29+
done(new Error('An Error Occurred'));
30+
}
31+
32+
describe('parallel', function(){
33+
34+
var taker;
35+
36+
beforeEach(function(done){
37+
taker = new Undertaker();
38+
taker.task('test1', fn1);
39+
taker.task('test2', fn2);
40+
taker.task('test3', fn3);
41+
taker.task('error', fnError);
42+
done();
43+
});
44+
45+
it('should take all string names', function(done){
46+
taker.parallel('test1', 'test2', 'test3')(function(err, results){
47+
expect(results).to.deep.equal([1, 2, 3]);
48+
done(err);
49+
});
50+
});
51+
52+
it('should take all functions', function(done){
53+
taker.parallel(fn1, fn2, fn3)(function(err, results){
54+
expect(results).to.deep.equal([1, 2, 3]);
55+
done(err);
56+
});
57+
});
58+
59+
it('should take string names and functions', function(done){
60+
taker.parallel('test1', fn2, 'test3')(function(err, results){
61+
expect(results).to.deep.equal([1, 2, 3]);
62+
done(err);
63+
});
64+
});
65+
66+
it('should take nested parallel', function(done){
67+
var parallel1 = taker.parallel('test1', 'test2', 'test3');
68+
taker.parallel('test1', parallel1, 'test3')(function(err, results){
69+
expect(results).to.deep.equal([1, [1, 2, 3], 3]);
70+
done(err);
71+
});
72+
});
73+
74+
it('should stop processing on error', function(done){
75+
taker.on('error', function(err){
76+
// to keep the process from crashing
77+
});
78+
taker.parallel('test1', 'error', 'test3')(function(err, results){
79+
expect(err).to.be.an.instanceof(Error);
80+
expect(results).to.deep.equal([1, undefined, undefined]);
81+
done();
82+
});
83+
});
84+
85+
it('should throw on unregistered task', function(done){
86+
function unregistered(){
87+
taker.parallel('unregistered');
88+
}
89+
90+
expect(unregistered).to.throw('Task never defined: unregistered');
91+
done();
92+
});
93+
});

test/registry.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
var lab = exports.lab = require('lab').script();
4+
var describe = lab.describe;
5+
var it = lab.it;
6+
var before = lab.before;
7+
var beforeEach = lab.beforeEach;
8+
var after = lab.after;
9+
var afterEach = lab.afterEach;
10+
var expect = require('lab').expect;
11+
12+
var Undertaker = require('../');
13+
14+
var DefaultRegistry = require('undertaker-registry');
15+
16+
function CustomRegistry(){}
17+
18+
describe('registry', function(){
19+
20+
it('should take a custom registry', function(done){
21+
var taker = new Undertaker(CustomRegistry);
22+
expect(taker.registry).to.be.an.instanceof(CustomRegistry);
23+
expect(taker.registry).to.not.be.an.instanceof(DefaultRegistry);
24+
done();
25+
});
26+
27+
it('should default to undertaker-registry if not constructed with custom registry', function(done){
28+
var taker = new Undertaker();
29+
expect(taker.registry).to.be.an.instanceof(DefaultRegistry);
30+
expect(taker.registry).to.not.be.an.instanceof(CustomRegistry);
31+
done();
32+
});
33+
});

0 commit comments

Comments
 (0)