index.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. 'use strict';
  2. const pMap = require('p-map');
  3. const Task = require('./lib/task');
  4. const TaskWrapper = require('./lib/task-wrapper');
  5. const renderer = require('./lib/renderer');
  6. const ListrError = require('./lib/listr-error');
  7. const runTask = (task, context, errors) => {
  8. if (!task.isEnabled()) {
  9. return Promise.resolve();
  10. }
  11. return new TaskWrapper(task, errors).run(context);
  12. };
  13. class Listr {
  14. constructor(tasks, opts) {
  15. if (tasks && !Array.isArray(tasks) && typeof tasks === 'object') {
  16. if (typeof tasks.title === 'string' && typeof tasks.task === 'function') {
  17. throw new TypeError('Expected an array of tasks or an options object, got a task object');
  18. }
  19. opts = tasks;
  20. tasks = [];
  21. }
  22. if (tasks && !Array.isArray(tasks)) {
  23. throw new TypeError('Expected an array of tasks');
  24. }
  25. this._options = Object.assign({
  26. showSubtasks: true,
  27. concurrent: false,
  28. renderer: 'default',
  29. nonTTYRenderer: 'verbose'
  30. }, opts);
  31. this._tasks = [];
  32. this.concurrency = 1;
  33. if (this._options.concurrent === true) {
  34. this.concurrency = Infinity;
  35. } else if (typeof this._options.concurrent === 'number') {
  36. this.concurrency = this._options.concurrent;
  37. }
  38. this._RendererClass = renderer.getRenderer(this._options.renderer, this._options.nonTTYRenderer);
  39. this.exitOnError = this._options.exitOnError;
  40. this.add(tasks || []);
  41. }
  42. _checkAll(context) {
  43. for (const task of this._tasks) {
  44. task.check(context);
  45. }
  46. }
  47. get tasks() {
  48. return this._tasks;
  49. }
  50. setRenderer(value) {
  51. this._RendererClass = renderer.getRenderer(value);
  52. }
  53. add(task) {
  54. const tasks = Array.isArray(task) ? task : [task];
  55. for (const task of tasks) {
  56. this._tasks.push(new Task(this, task, this._options));
  57. }
  58. return this;
  59. }
  60. render() {
  61. if (!this._renderer) {
  62. this._renderer = new this._RendererClass(this._tasks, this._options);
  63. }
  64. return this._renderer.render();
  65. }
  66. run(context) {
  67. this.render();
  68. context = context || Object.create(null);
  69. const errors = [];
  70. this._checkAll(context);
  71. const tasks = pMap(this._tasks, task => {
  72. this._checkAll(context);
  73. return runTask(task, context, errors);
  74. }, {concurrency: this.concurrency});
  75. return tasks
  76. .then(() => {
  77. if (errors.length > 0) {
  78. const err = new ListrError('Something went wrong');
  79. err.errors = errors;
  80. throw err;
  81. }
  82. this._renderer.end();
  83. return context;
  84. })
  85. .catch(err => {
  86. err.context = context;
  87. this._renderer.end(err);
  88. throw err;
  89. });
  90. }
  91. }
  92. module.exports = Listr;