Socket
Socket
Sign inDemoInstall

listr

Package Overview
Dependencies
36
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.5.0 to 0.6.0

lib/renderer.js

29

index.js
'use strict';
const Task = require('./lib/task');
const CLIRenderer = require('./lib/renderer').CLIRenderer;
const renderers = require('./lib/renderer');
const getRenderer = renderer => {
if (typeof renderer === 'string') {
return renderers[renderer] || renderers.default;
}
return renderer || renderers.default;
};
class Listr {

@@ -17,14 +25,17 @@

this._RendererClass = CLIRenderer;
this._tasks = [];
this._options = Object.assign({
showSubtasks: true,
concurrent: false
concurrent: false,
renderer: 'default'
}, opts);
this._tasks = [];
this._RendererClass = getRenderer(this._options.renderer);
this.level = 0;
this.add(tasks || []);
}
get tasks() {
return this._tasks;
}
setRenderer(renderer) {

@@ -46,3 +57,3 @@ this._RendererClass = renderer;

if (!this._renderer) {
this._renderer = new this._RendererClass(this._tasks);
this._renderer = new this._RendererClass(this._tasks, this._options);
}

@@ -68,5 +79,3 @@

.catch(err => {
if (this.level === 0) {
this._renderer.end();
}
this._renderer.end(err);
throw err;

@@ -73,0 +82,0 @@ });

'use strict';
module.exports = {
const state = {
PENDING: 0,

@@ -8,1 +8,18 @@ COMPLETED: 1,

};
state.toString = input => {
switch (input) {
case state.PENDING:
return 'pending';
case state.COMPLETED:
return 'completed';
case state.FAILED:
return 'failed';
case state.SKIPPED:
return 'skipped';
default:
return 'unknown';
}
};
module.exports = state;
'use strict';
const Ora = require('ora');
const logSymbols = require('log-symbols');
const figures = require('figures');
const chalk = require('chalk');
const indentString = require('indent-string');
const isStream = require('is-stream');
const isPromise = require('is-promise');
const streamToObservable = require('stream-to-observable');
const stripAnsi = require('strip-ansi');
const cliTruncate = require('cli-truncate');
const StringRenderer = require('./renderer').StringRenderer;
const Subject = require('rxjs/Subject').Subject;
const renderers = require('./renderer');
const state = require('./state');
const color = 'yellow';
const pointer = chalk[color](figures.pointer);
const skipped = chalk[color](figures.arrowDown);
const isListr = obj => obj && obj.setRenderer && obj.add && obj.run;
// https://github.com/sindresorhus/is-observable/issues/1
const isObservable = obj => obj && obj.subscribe && obj.forEach;
const isObservable = obj => obj && typeof obj.subscribe === 'function' && typeof obj.constructor.create === 'function';
const getSymbol = task => {
switch (task.state) {
case state.PENDING:
return task.showSubtasks() ? `${pointer} ` : task._spinner.frame();
case state.COMPLETED:
return `${logSymbols.success} `;
case state.FAILED:
return task._result ? `${pointer} ` : `${logSymbols.error} `;
case state.SKIPPED:
return `${skipped} `;
default:
return ' ';
}
};
const defaultSkipFn = () => false;
class Task {
class Task extends Subject {
constructor(listr, task, options) {
super();
if (!task) {

@@ -61,3 +38,4 @@ throw new TypeError('Expected a task');

this._options = options || {};
this._spinner = new Ora({color});
this._subtasks = [];
this._output = undefined;

@@ -69,28 +47,42 @@ this.title = task.title;

showSubtasks() {
return this._result && (this._options.showSubtasks !== false || this.state === state.FAILED);
get output() {
return this._output;
}
render() {
const skipped = this.state === state.SKIPPED ? ` ${chalk.dim('[skipped]')}` : '';
let out = indentString(` ${getSymbol(this)}${this.title}${skipped}`, ' ', this._listr.level);
get subtasks() {
return this._subtasks;
}
if (this.showSubtasks()) {
const output = this._result.render();
if (output !== null) {
out += `\n${output}`;
}
}
set state(state) {
this._state = state;
if ((this.state === state.PENDING || this.state === state.SKIPPED) && this._output) {
const lastLine = stripAnsi(this._output.trim().split('\n').pop().trim());
if (lastLine) {
const output = indentString(`${figures.arrowRight} ${lastLine}`, ' ', this._listr.level);
out += `\n ${chalk.gray(cliTruncate(output, process.stdout.columns - 3))}`;
}
}
this.next({
type: 'STATE'
});
}
return out;
get state() {
return state.toString(this._state);
}
hasSubtasks() {
return this._subtasks.length > 0;
}
isPending() {
return this._state === state.PENDING;
}
isSkipped() {
return this._state === state.SKIPPED;
}
isCompleted() {
return this._state === state.COMPLETED;
}
hasFailed() {
return this._state === state.FAILED;
}
run() {

@@ -100,5 +92,9 @@ const handleResult = result => {

if (isListr(result)) {
result.level = this._listr.level + 1;
result.setRenderer(StringRenderer);
this._result = result;
result.setRenderer(renderers.silent);
this._subtasks = result.tasks;
this.next({
type: 'SUBTASKS'
});
return result.run();

@@ -118,2 +114,7 @@ }

this._output = data;
this.next({
type: 'DATA',
data
});
},

@@ -141,6 +142,6 @@ error: reject,

if (skipped) {
this.state = state.SKIPPED;
if (typeof skipped === 'string') {
this._output = skipped;
}
this.state = state.SKIPPED;
return;

@@ -152,3 +153,3 @@ }

.then(() => {
if (this.state === state.PENDING) {
if (this.isPending()) {
this.state = state.COMPLETED;

@@ -160,2 +161,6 @@ }

throw err;
})
.then(() => {
// Mark the Observable as completed
this.complete();
});

@@ -162,0 +167,0 @@ }

{
"name": "listr",
"version": "0.5.0",
"version": "0.6.0",
"description": "Terminal task list",

@@ -46,5 +46,9 @@ "license": "MIT",

"is-stream": "^1.1.0",
"listr-silent-renderer": "^1.0.0",
"listr-update-renderer": "^0.1.1",
"listr-verbose-renderer": "^0.1.0",
"log-symbols": "^1.0.2",
"log-update": "^1.0.2",
"ora": "^0.2.3",
"rxjs": "^5.0.0-beta.11",
"stream-to-observable": "^0.1.0",

@@ -57,3 +61,3 @@ "strip-ansi": "^3.0.1"

"delay": "^1.3.1",
"rxjs": "^5.0.0-beta.9",
"hook-std": "^0.2.0",
"xo": "*"

@@ -63,8 +67,3 @@ },

"esnext": true
},
"clinton": {
"rules": {
"editorconfig": "off"
}
}
}

@@ -31,3 +31,3 @@ # listr [![Build Status](https://travis-ci.org/SamVerschueren/listr.svg?branch=master)](https://travis-ci.org/SamVerschueren/listr)

}
});
})
},

@@ -40,3 +40,3 @@ {

}
});
})
}

@@ -66,3 +66,3 @@ ], {concurrent: true});

### Task
## Task

@@ -87,3 +87,3 @@ 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.

#### Promises
### Promises

@@ -96,3 +96,3 @@ A `task` can also be async by returning a `Promise`. If the promise resolves, the task completed successfully, it it rejects, the task failed.

title: 'Success',
task: () => Promise.resolve('Foo');
task: () => Promise.resolve('Foo')
},

@@ -106,3 +106,3 @@ {

#### Observable
### Observable

@@ -139,3 +139,3 @@ <img src="media/observable.gif" width="250" align="right">

#### Streams
### Streams

@@ -145,3 +145,3 @@ It's also possible to return a `stream`. The stream will be converted to an `Observable` and handled as such.

#### Skipping tasks
### Skipping tasks

@@ -180,3 +180,58 @@ <img src="media/skipped.png" width="250" align="right">

## Custom renderers
It's possible to write custom renderers for Listr. A renderer is an ES6 class that accepts the tasks that it should renderer, and the Listr options object. It has two methods, the `render` method which is called when it should start rendering, and the `end` method. The `end` method is called all the tasks are completed or if a task failed. If a task failed, the error object is passed in via an argument.
```js
class CustomRenderer {
constructor(tasks, options) { }
render() { }
end(err) { }
}
module.exports = CustomRenderer;
```
> Note: A renderer is not passed through to the subtasks, only to the main task. It is up to you to handle that case.
### Observables
Every task is an observable. The task emits three different events and every event is an object with a `type` property.
1. The state of the task has changed (`STATE`).
2. The task outputted data (`DATA`).
3. The task returns a subtask list (`SUBTASKS`).
This allows you to flexibly build up your UI. Let's render every task that starts executing.
```js
class CustomRenderer {
constructor(tasks, options) {
this._tasks = tasks;
this._options = Object.assign({}, options);
}
render() {
for (const task of this._tasks) {
task.subscribe(event => {
if (event.type === 'STATE' && task.isPending()) {
console.log(`${task.title} [started]`);
}
});
}
}
end(err) { }
}
module.exports = CustomRenderer;
```
If you want more complex examples, take a look at the [update](https://github.com/SamVerschueren/listr-update-renderer) and [verbose](https://github.com/SamVerschueren/listr-verbose-renderer) renderers.
## API

@@ -212,10 +267,4 @@

##### showSubtasks
Any renderer specific options.
Type: `boolean`<br>
Default: `true`
Set to `false` if you want to disable the rendering of the subtasks. Subtasks will be rendered if
an error occurred in one of them.
##### concurrent

@@ -228,2 +277,10 @@

##### renderer
Type: `string` `object`<br>
Default: `default`<br>
Options: `default` `verbose` `silent`
Renderer that should be used. You can either pass in the name of the known renderer, or a class of a custom renderer.
### Instance

@@ -230,0 +287,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc