It turns out that making a task runner is not that difficult. Well... making a good task runner might be difficult but building something that just runs functions is not.
Just for fun I took a look inside the code of @ygor/task and saw how simple it was. Decided to make myself a version of that, one that was designed not to live inside javascript project. So I could have something like this.
task do-stuff
# stuff happens
That's it. The thing lives here: taskmachine.
Why?
make
and a million other tools do this. Then why? I was bored. Also, a Makefile
gets kinda weird as soon as you start doing some bash-kung-fu inside of it. If I'm going to do some kung-fu fighting might as well do it in javascript, at least I could understand it a little bit better and without google help.
Show me the money
I mentioned that this tool wasn't created to be in a javascript project. This is actually better as lonely script in an alias.
alias task='node /path/to/taskmachine.js ./make.js'
Now you can create a make.js
file.
// make.js
const log = (name) => (...args) => console.log(name, args[0]);
module.exports = function(tasks) {
tasks
.add('test', 'Run some tests',log('test'))
.add('cover', log('cover'));
}
You call one of the tasks.
task test
And you should have.
[15:32:33] Starting 'test' ...
test { _: [] }
[15:32:33] Finished 'test' (10ms)
If you want to add some arguments, you're more than welcome.
task test --foo 1234 hi --foo 5678 there -- --foo 2468
[15:33:56] Starting 'test' ...
test { _: [ 'hi', 'there', '--foo', '2468' ], foo: '5678' }
[15:33:56] Finished 'test' (9ms)
See that foo
outside the array? Is a property of args[0]
. You get the flags from the cli as a plain object. The _
gets the positional arguments and the --
stops the argument parsing, so everything after that is included as is.
If you omit the task name it will try to run a task named default
. If it can't find the default
task then it shows a list of available tasks.
Available tasks:
* test: Run some tests
* cover
If you do have a default
task but you still want that list, use the addlist
method.
const log = (name) => (...args) => console.log(name, args[0]);
module.exports = function(tasks) {
tasks
.add('test', 'Run some tests',log('test'))
.add('cover', log('cover'))
+ .add('default', log('default'))
+ .addlist('list');
}
Calling task list
gets you.
[22:30:58] Starting 'list' ...
Available tasks:
* test: Run some tests
* cover
* default
* list: List available tasks
[22:30:58] Finished 'list' (5ms)
If you don't want the timestamps use the --quiet/-q
flag.
One cool trick this thing can do is creating subtasks
. Yes, tasks within tasks.
// make.js
function childA1() { console.log('hi from a1'); }
function childA2() { console.log('hi from a2'); }
function parentA(cli, { tasks }) {
// Subtasks
return tasks()
.add('1', childA1)
.add('2', childA2);
}
function childB1() { console.log('hi from b1'); }
function childB2() { console.log('hi from b2'); }
function parentB(cli, { tasks }) {
// Subtasks
return tasks()
.add('1', childB1)
.add('2', childB2);
}
module.exports = function(tasks) {
tasks
.add('a', parentA)
.add('b', parentB);
}
Call task b 1 --quiet
.
hi from b1
At some point you would want to call external commands, so I added execa.command. You can access it from the second argument of the function as sh
.
async function build(args, { sh }) {
await sh('serious-command --important --not-really');
}
module.exports = function(tasks) {
tasks
.add('build', build)
}
sh
doesn't use a shell so don't do any kung-fu in it. It's just there to call other commands.
Should people use this?
No. This is a toy project. Don't do anything serious with this. If you really want something like this, use this one: just.
Top comments (0)