trun

task runner

npm install trun
1 downloads in the last week
13 downloads in the last month

trun

trun is simple task runner. In many cases it's better than make for node.js projects management. trun tasks are described as js module, so they are fully js-powered.

trun provides number of entities which can help you to hide complex and ugly things and keep your tasks simple and elegant. But at any point you can use regular js function with any functionality.

trun has focus on simple running shell commands, because this is what you need often. It hides asynchronous nature of corresponding node.js functionality making running sets of shell commands very easy.

All trun syntax sugar providing classes are extandable, so you can easily create your own WrappedTask or Resolvable providing some sugar for your regular tasks.

It's recommended to:

  • store your tasks in file named tasks.js
  • add alias run='node tasks.js' to your shell profile

running the task

Assuming you have run alias mentioned above. If not, use node tasks.js instead of run.

# run default task
run

# run task hello
run hello

# run task sometask
run sometask

# run task hello with arguments
run hello world "a b c" 123

# run default task with arguments
run - arg1 arg2

tasks.js example

It's located in example directory and all task running examples provided above will work with it. The only difference is that it references trun library as '../lib'.

"use strict";
var trun = require('trun');
var run = trun.wrapped.run;
var apply = trun.wrapped.apply;
var print = trun.wrapped.print;
var args = trun.resolvable.args;

var runner = new trun.Runner();
runner.addTasks({
    default:
        'dev',

    dev: [
        apply('hello', args),
        'compile',
        'run'
    ],

    hello:
        print('hello ', args.cmdArgs),

    compile:
        print('compiling...'),

    run: function (cb) {
        // do something useful
        this.runTasks([
            // using wrapped tasks within custom function
            run('echo ', args)
        ], ['running'], cb);
    },

    otherTask:
        print('othertask says: ', args.get(0)),

    sometask: [
        'hello',
        function () {
            var args = this.getArgs(arguments);
            var cb = this.getCb(arguments);
            this.print('sometask is called with arguments: ', this.toCmdArgs(args));
            this.tasks.otherTask('hi there', cb);
        }
    ]
});
runner.start();

More complex example can be found in test/tasks.js.

Main principles

  • every task has name - key in dictionary argument of runner.addTasks()
  • every task is an asynchronous function
  • every task's function last argument is a callback that must be called when task is completed
    • first argument of callback function is error, it must be null or undefined if no error occured
    • any count of other arguments are 'result'
    • if error passed to callback has non-null exitCode property and will cause termination, program will exit with given exit code
    • if error is instance of trun.errors.Exit and will cause termination, program will exit silently (without stacktrace or something)
  • if task function has no arguments in it's definition, it is treated as variable length arguments function
    • it can be called with any number of arguments
    • but last argument must be a callback
  • if task function has some arguments, it is treated as fixed length arguments function and it's last argument will always be used for callback

also

  • every task function, when called has runner instance provided as this
    • so, can use utilities and other methods of runner
  • you can call other tasks from your task function, tasks dictionary will be provided as this.tasks and all tasks will be already bound to runner
  • of course, you can also require any libs and run any code before, after or within your tasks definitions

So, typical task function may look like:

function (a, b, c, cb) { // fixed length args
    // do something
    this.print('hi )'); // using runner methods
    cb(null, 12); // result is 12
}

or

function () { // variable length args
    var args = this.getArgs(arguments); // using util to get arguments except callback
    var cb = this.getCb(arguments); // same for cb
    this.print(args);
    cb(); // don't forget to call cb
}

And other task call may look like

this.tasks.otherTask(arg1, arg2, cb);

or

this.tasks.otherTask.apply(null, [arg1, arg2, cb]);

cb.ctx

Callback function may have ctx object attached to it. If it is present, it may contain following properties:

  • prevResult - result array passed to callback by previously runned task
  • box - dictionary shared between all calls in context of one arr task wrapper
    • can be used to pass a value to some of next tasks

ctx is usually available in context of arr task wrapper, see below.

runner methods and properties

Any task function's this references runner object, so all methods and properties below are available for it.

  • tasks - references tasks dictionary, you can find examples of running other tasks from it above
  • runTasks(tasks, args, cb) - wraps tasks into arr and runs obtained task function with given arguments
    • allows to use wrapped tasks within your custom task function
  • getArgs(arguments) - returns arguments without last one which is callback by agreement
    • useful for variable length arguments handling, see above
  • getCb(arguments) - returns last argument which is callback by agreement
    • also for variable length arguments handling, see above
  • run(arg1, ..., cb) - flattens and concatenates arguments then runs obtained string as a shell command
    • generates an error if command exit code is not 0
  • prun(arg1, ..., cb) - as run but prints command before executing it
  • tryRun(areg1, ..., cb) - like run but doesn't generate error if exit code is not 0, provides exit code as a result instead
  • tryPrun(arg1, ..., cb) - like tryRun, but prints command before executing it
  • toCmdArgs(args) - escapes given arguments to be suitable to form command line arguments
  • joinStr(parts) - flattens and joins parts into single string
  • print(arg1, ...) - flattens, concatenates and prints arguments
  • exit(cb, opt_code) - produces Exit error with give exit code

Sugar

There are two kinds of sugar entities:

  • WrappedTask - functions which generate task functions
  • Resolvable - objects that can describe some data to be used by WrappedTask functions which must be resolved at execution time

Conversion to WrappedTask

  • if task is Array, it will be converted to arr
  • if task is String, it will be converted to:
    • alias for top-level tasks
    • call for any other

WrappedTask functions

WrappedTask functions are located in trun.wrapped module.

  • arr(task1, ...) - represents set of tasks that will be executed one by one
    • if any of tasks calls callback with error, following tasks will be skipped and arr's callback will be called with error immediately
    • arr attempts to pass to underlying tasks as many it's arguments as they are ready to receive
  • toBox(k, v) - will put value v to 'box' under key k, box exists in context of arr() set of tasks only
    • you can use box resolvable to access stored value
    • also you can use cb.ctx.box to access box from within your function
  • print(arg1, ...) - prints flattens, concatenates and prints arguments
    • understands resolvables at any level of depth
  • result(arg1, ...) - calls it's callback providing arguments as result
    • mainly for using in arr() context
    • result array can be accessed by prev resolvable
    • also result can be obtained using cb.ctx.prevResult from within your function
  • run(arg1, ...) - flattens and concatenates arguments then runs obtained string as a shell command
    • understands resolvables at any level of depth
    • generates an error if command exit code is not 0
  • prun(arg1, ...) - like run but prints command before executing it
  • tryRun(arg1, ...) - like run but doesn't generate error if exit code is not 0, provides exit code as a result instead
    • exit code can then be accessed via prev resolvable or cb.ctx.prevResult
  • tryPrun(arg1, ...) - like tryRun, but prints command before executing it
  • alias(name) - runs task with given name traversing arguments to it
  • call(name, arg1, ...) - runs task with given name providing given arguments to it
    • understands resolvables as any of arguments, but not their internal parts
  • apply(name, [arg1, ...]) - like call, but arguments must be specified as an array
  • exit(code) - produces Exit error
    • understands resolvables as code

Resolvable objects

Resolvable objects are located in trun.resolvable module.

  • args - represents arguments passed to this context
  • box - represents box shared between all task functions in arr context
  • custom(f(runner, ctx)) - returns result of calling given function which will have runner and ctx as arguments
  • prev - represents prevResult, result array of previously runned task in arr context

args and prev have following methods and properties:

  • slice(start, end) - provides slice of value
  • get(pos) - provides single element
  • cmdArgs - applies toCmdArgs() on value (see above)

box has following methods and properties:

  • get(k) - gets value with key k from box
  • cmdArgs - applies toCmdArgs() on value (see above)

License

MIT

npm loves you