Terminal task list
$ npm install --save listr
import execa from 'execa';
import Listr from 'listr';
const tasks = new Listr([
{
title: 'Git',
task: () => {
return new Listr([
{
title: 'Checking git status',
task: () => execa.stdout('git', ['status', '--porcelain']).then(result => {
if (result !== '') {
throw new Error('Unclean working tree. Commit or stash changes first.');
}
})
},
{
title: 'Checking remote history',
task: () => execa.stdout('git', ['rev-list', '--count', '--left-only', '@{u}...HEAD']).then(result => {
if (result !== '0') {
throw new Error('Remote history differ. Please pull changes.');
}
})
}
], {concurrent: true});
}
},
{
title: 'Install package dependencies with Yarn',
task: (ctx, task) => execa('yarn')
.catch(() => {
ctx.yarn = false;
task.skip('Yarn not available, install it via `npm install -g yarn`');
})
},
{
title: 'Install package dependencies with npm',
enabled: ctx => ctx.yarn === false,
task: () => execa('npm', ['install'])
},
{
title: 'Run tests',
task: () => execa('npm', ['test'])
},
{
title: 'Publish package',
task: () => execa('npm', ['publish'])
}
]);
tasks.run().catch(err => {
console.error(err);
});A task can return different values. If a task returns, it means the task was completed successfully. If a task throws an error, the task failed.
const tasks = new Listr([
{
title: 'Success',
task: () => 'Foo'
},
{
title: 'Failure',
task: () => {
throw new Error('Bar')
}
}
]);A task can also be async by returning a Promise. If the promise resolves, the task completed successfully, if it rejects, the task failed.
const tasks = new Listr([
{
title: 'Success',
task: () => Promise.resolve('Foo')
},
{
title: 'Failure',
task: () => Promise.reject(new Error('Bar'))
}
]);Tip: Always reject a promise with some kind of
Errorobject.
A task can also return an Observable. The thing about observables is that it can emit multiple values and can be used to show the output of the
task. Please note that only the last line of the output is rendered.
import {Observable} from 'rxjs';
const tasks = new Listr([
{
title: 'Success',
task: () => {
return new Observable(observer => {
observer.next('Foo');
setTimeout(() => {
observer.next('Bar');
}, 2000);
setTimeout(() => {
observer.complete();
}, 4000);
});
}
},
{
title: 'Failure',
task: () => Promise.reject(new Error('Bar'))
}
]);You can use the Observable package you feel most comfortable with, like RxJS or zen-observable.
It's also possible to return a ReadableStream. The stream will be converted to an Observable and handled as such.
import fs from 'fs';
import split from 'split';
const list = new Listr([
{
title: 'File',
task: () => fs.createReadStream('data.txt', 'utf8')
.pipe(split(/\r?\n/
