# @billogram/task-runner

> A simple task runner

## Install

```
yarn add @billogram/task-runner
```

## Usage

Define a task.

```
export default function customTask() {
    return async function run(name: string; context: TaskContext) {
        // Do something.
    }
}
```

Add the task to a task runner.

```
import TaskRunner from '@billogram/task-runner';
import customTask from './customTask';


const runner = new TaskRunner('build-scripts');
runner.add('custom-task', customTask());

runner.addSequence('custom-sequence', [
    'custom-task',
]);

runner.addSequence('custom-sequence-with-context', [
    'custom-task',
], {
    silent: true,
});

runner.addSequence('custom-sequence-with-hooks', {
    pre: [
        // add any pre tasks here.
    ],
    script: [
        'custom-task',
    ],
    post: [
        // add any post tasks here.
    ],
});

runner.addSequence('pre-task-sequence, [
    // add tasks here.
]);

runner.addSequence('post-task-sequence, [
    // add tasks here.
]);

runner.addSequence('custom-sequence-with-hooks-simple', {
    pre: 'pre-task-sequence',
    script: [
        'custom-task',
    ],
    post: 'post-task-sequence',
});

runner.start('custom-task', {
    skipPreScript: false,
    skipScript: false,
    skipPostScript: false,
});

// or...

runner.start('custom-task', {
    skipPreScript: [],
    skipScript: [],
    skipPostScript: [],
});
```

## API

Information about types used in the task runner can be found [here](https://github.com/billogram/frontend-dev-tools/blob/master/packages/tasks/task-runner/src/types.ts).

### `TaskContext`

A `TaskContext` is passed to every task. The context has the following properties:

```
{
    // Should the sequence tasks be run concurrently.
    concurrent: TaskContextConcurrentType;
    // The build environment.
    env?: 'development' | 'production';
    // Any flags that was passed to the task runners start method.
    flags: TaskFlags;
    // A flag to determine if the task should be run in silent mode. 
    // It is the responsibility of the task to define what this means.
    silent: boolean;
    // Run a specific executable with the specified arguments. The exit
    // code of the executable is the return value of this function.
    run(bin: string, args: string[], opts: CommonOptions): Promise<TaskContextRunResult>;
}
```

The `TaskRunner` uses [`execa`](https://github.com/sindresorhus/execa) internally and `opts` are the [options](https://github.com/sindresorhus/execa#options) for `execa`.

### `TaskHandler`

A task is a function with the following signature.

`type TaskHandler = (name: string, context: TaskContext) => Promise<TaskContextRunResult>;`

### `TaskRunner`

The `TaskRunner` is used for coordinating the task execution.

#### `constructor(scriptName: string)`

The `scriptName` is the name that will be displayed together with command name when running a command (task).

#### `commands(): string[]`

A list of the names of all the tasks that have been added to the task runner.

#### `add(name: string, handler: TaskHandler): void`

Add a task to the task runner.

#### `addSequence(name: string, sequence: TaskSequence, context?: Partial<TaskContext>): void`

Add a sequence of tasks to the task runner with an optional custom context.

#### `start(name: string, flags: TaskFlags = {}): void`

Start a specific command (task). Flags will be passed to the `TaskContext`.

There are a number of special flags: `skipPreScript`, `skipScript`, and `skipPostScript`. These will not be passed to the `TaskContext` instead of they will be used to skip either the `pre`, `script`, or `post` phase of a task sequence.

## Note

This library is being published with our use cases in mind and is not necessarily meant to be consumed by the broader public. We probably won't take your feature requests unless they align with our own needs.

## License

MIT
