Giter Club home page Giter Club logo

listr2's Introduction

listr2's People

Contributors

agirton avatar ai avatar ajhenry avatar alexpsi avatar alopix avatar andarist avatar andywer avatar arfatsalman avatar athomann avatar beeequeue avatar blakef avatar cenk1cenk2 avatar chris-olszewski avatar dependabot[bot] avatar grebenschikov avatar guilhermetod avatar innocenzi avatar insipx avatar jurijzahn8019 avatar k15a avatar kostasx avatar marcelmeulemans avatar mathiasbynens avatar mike-north avatar nickymeuleman avatar okonet avatar reconbot avatar renovate-bot avatar samverschueren avatar unkillbob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

listr2's Issues

Add ability to allow custom enquirer editors

I'm currently using this function inspired by (copied from) the prompt method:

   function createCustomPrompt(task, Prompt, options) {
     task.prompt = true;
     let buffer = Buffer.alloc(64);
  
     const outputStream = through((data) => {
       buffer += data;
  
       // eslint-disable-next-line no-control-regex
       const deleteMultiLineRegexp = new RegExp(/.*(\u001b\[[0-9]*G|\u0007).*/m);          12
       if (deleteMultiLineRegexp.test(buffer.toString())) {
         buffer = Buffer.alloc(64);
        } else {
          task.output = buffer.toString();
        }
      });

      Object.assign(options, { stdout: outputStream });
      return new Prompt(options);
    }

With for example the enquirer-editor like this:

import EditorPrompt from 'enquirer-editor';
import { Manager } from 'listr2';

const manager = new Manager();
manager.add({
  title: 'Editor',
  task: async (_, task) => {
    const prompt = createCustomPrompt(task, EditorPrompt, { type: 'editor', message: 'Please Fill' });
    const message = await prompt.run();
  }
})
manager.runAll();

This works quite well, I was just wondering, @cenk1cenk2 do you think there's a way to incorporate this into listr2 somehow?
Or maybe make the prompt method from TaskWrapper more versatile to accept custom prompt classes?

No valid exports for `listr2/node_modules/uuid`

Running lint-staged (using listr2 2.0.1 https://github.com/okonet/lint-staged/blob/master/package.json#L41) fails when running with the following stack:

husky > pre-commit (node v13.3.0)
internal/modules/cjs/loader.js:621
  throw e;
  ^

Error: No valid exports main found for 'project/node_modules/listr2/node_modules/uuid'
    at resolveExportsTarget (internal/modules/cjs/loader.js:618:9)
    at applyExports (internal/modules/cjs/loader.js:499:14)
    at resolveExports (internal/modules/cjs/loader.js:548:12)
    at Function.Module._findPath (internal/modules/cjs/loader.js:650:22)
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:948:27)
    at Function.Module._load (internal/modules/cjs/loader.js:854:27)
    at Module.require (internal/modules/cjs/loader.js:1023:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (project/node_modules/listr2/dist/lib/task.js:9:16)
    at Module._compile (internal/modules/cjs/loader.js:1128:30) {
  code: 'MODULE_NOT_FOUND'
}
husky > pre-commit hook failed (add --no-verify to bypass)

I've tried removing node_modules and package-lock and re-installing but no luck πŸ˜”

Testing console output

Hello,

we're in the process of migrating lint-staged to Listr2, but I have some question regarding test output assertion.

The orginal Listr's verbose renderer printed [started] and [completed] strings, while Listr2 uses fancy symbols like ❯ and βœ”. These symbols are different on each platform, though, so testing in a CI environment is a bit difficult.

You can see the progress in the PR lint-staged/lint-staged#852 and how the assertions fail on our Windows tests: https://ci.appveyor.com/project/okonet/lint-staged/builds/32413566/job/qyae7t039cckykre

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)

Question: Is there a way to modify a task's title after all the subtasks have completed successfully

I'm currently using Listr2 to run a set of subtasks, and I wanted to know if there's a way to change the title of the parent, on succesful completion. For eg. in the snippet below, I'd like to change Uploading to Uploaded once all the subtasks are done.

// `uploadTasks` -> an array of ListrTask objects
new Listr([
 title: "Uploading some docs",
 task: async (_, task) => task.newListr(uploadTasks, listrOptions);
]});

I'm not sure if I'm missing something here, but since task.newListr returns a Listr object, and not a Promise, I cannot update the task.title from there. Would be great if you could let me know of a way to do this. Thanks!

Do not swallow error message when prompt is enabled

The error message is replaced with 'Cancelled the prompt' when a task is to be marked as failed by the developer but a prompt was used in it.

image

Maybe there could be a task.fail method instead to distinguish between exceptions thrown from internal packages (if that is the concern) and custom exceptions (signalling a task has failed because of whatever the user put in).

Option to Disable Truncation / Empty Line removal?

Hi there! πŸ‘‹

First of all, thanks for your contribution of listr2 to the community! This is a great library, and saves a bunch of boilerplate!

I am a bit confused with listr2's behavior of truncating and removing empty lines in my errors. The content and the formatting that I'm writing in the errors is important, and I would like it to stay the same.

See the error in the source code and the formatting in the terminal. The first line of the error is truncated and the empty line is removed:

Screen Shot 2021-01-16 at 16 54 57

Here are our options:

{
  exitOnError: false,
  rendererOptions: { collapseErrors: false },
  concurrent: 5,
}

It seems like this could also be a default for listr2, but maybe there's a reason why that's not a good idea.

cc @Josehower

Enquirer multi-step prompts

Awesome work on bringing old listr back to life!

One small nuance that is pretty annoying though: currently listr2 does not have support for multi-step enquirer prompts. It would be amazing, if this feature could be added.

{
  title: "Configure",
  task: async (ctx, task) => {
    ctx.input = await task.prompt([
      {
        type: 'input',
        name: 'name',
        message: 'What is your name?'
      },
      {
        type: 'input',
        name: 'username',
        message: 'What is your username?'
      }
    ]);
  },
}

Upcoming TypeScript changes to Enquirer

I wanted to leave a trace here about a promising PR in the enquirer repo regarding TypeScript definitions (enquirer/enquirer#307).

I understand that the typings provided by listr2 are an internal reproduction of Enquirer's typings, although they are incomplete. Hopefully once the above PR is merged and published, the custom typings in listr2 can be removed!

Thanks for all the hard work on this great package btw! I love the developer experience here πŸš€

Testing prompts

Hello.

I am trying since a while to determine how I am supposed to create tests for the prompts. Using Enquirer directly, I can use its events, but using Listr, I don't have access to the underlying Enquirer object.

Is there currently any way to test prompts? Thanks!

EDIT - I think the ability to pass an instance of Enquirer, the same as logger, to a Listr object, would solve the issue, because we would be able to pass a fake Enquirer object, hence, to test it.

How to output stream progress

Hey πŸ‘‹

I've got a download stream with on('progress') event:

{
  title: 'Download task',
  task: () => {
    const stream = downloadStream(videoUrl)
      .on('progress', ({ num }, totalSegments, bytes) => {
        // send to listr
      })

    stream.pipe(fs.createWriteStream('videofile.mp4'))

    return stream
  }
}

If I use above code, chunks of downloaded data will be shown in console. I'd love to show message from progress event.

I don't have enough knowledge with streams, I've tried some ideas but didn't succeed. Is it somehow possible?

Dependency Dashboard

This issue provides visibility into Renovate updates and their statuses. Learn more

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • fix(deps): update dependency colorette to ^2.0.19

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

docker-compose
docker-compose.yml
  • cenk1cenk2/node-fnm latest
droneci
.drone.yml
  • node current-alpine
  • node current-alpine
  • node current-alpine
  • node current-alpine
  • node current-alpine
  • cenk1cenk2/drone-semantic-release no version found
  • plugins/downstream no version found
github-actions
.github/workflows/nodejs.yml
  • actions/checkout v2
  • actions/setup-node v2
  • actions/checkout v2
  • actions/setup-node v2
  • actions/checkout v2
  • actions/setup-node v2
.github/workflows/semantic-release.yml
  • actions/checkout v2
  • cycjimmy/semantic-release-action v2.7.0
.github/workflows/sync.yml
  • actions/checkout v2
  • TreTuna/sync-branches 1.4.0
.github/workflows/test-coverage.yml
  • actions/checkout v2
  • actions/setup-node v2
  • codecov/codecov-action v2
npm
package.json
  • cli-truncate ^2.1.0
  • colorette ^2.0.16
  • log-update ^4.0.0
  • p-map ^4.0.0
  • rfdc ^1.3.0
  • rxjs ^7.5.5
  • through ^2.3.8
  • wrap-ansi ^7.0.0
  • @cenk1cenk2/cz-cc ^1.4.11
  • @cenk1cenk2/eslint-config 2.5.5
  • @types/clone ^2.1.1
  • @types/jest ^27.4.0
  • @types/node ^17.0.14
  • @types/through ^0.0.30
  • @types/wrap-ansi ^3.0.0
  • delay ^5.0.0
  • enquirer ^2.3.6
  • eslint ^8.8.0
  • jest ^27.4.7
  • jest-mock-process ^1.4.1
  • lint-staged ^12.3.2
  • prettier ^2.5.1
  • rimraf ^3.0.2
  • simple-git-hooks ^2.7.0
  • ts-jest ^27.1.3
  • ts-node ^10.4.0
  • tsconfig-paths ^3.12.0
  • tsup 5.11.13
  • typedoc ^0.22.11
  • typedoc-plugin-markdown ^3.11.12
  • typescript ^4.6.0-dev.20220131
  • enquirer >= 2.3.0 < 3
  • node >=12
nvm
.nvmrc
  • node 16

  • Check this box to trigger a request for Renovate to run again on this repository

Output not preserved on error

When using the default renderer, and the following options

Renderer options:

concurrent: false,
rendererOptions: {
    collapse: false,
    showSubtasks: true
}

Task options:

persistentOutput: true,
exitOnError: true,
bottomBar: Infinity

When an error is throw by a task, the output that it previously posted to the bottom bar is cleared, even though output from previous successful tasks are preserved.

Is there a way to preserve output even if an error is thrown?
If not, perhaps a task option for preserveOutputOnError can be added?

edge case: last log line

First run the following exactly as is, then uncomment line 14 and re-run it:

const { Listr } = require('Listr2');

const tasks = new Listr([
  {
    title: 'Demo of edge case',
    task: async (ctx, task) => {
      console.log('I thought I was losing my mind.')
      console.log('Turns out that I\'m not losing it (yet), it\'s just an edge case.')
      console.log('Specifically, when the task includes:')
      console.log('options: {\n\tpersistentOutput: true\n}')
      console.log('and the Listr options include:')
      console.log('{\n\trendererOptions: { collapse: false }\n}')
      console.error('Then the last displayable line of either a console.log or console.error (and presumably, their other variations, e.g. console.warn, console.table, etc) is overwritten')
      // console.log('unless the last line ends with a \\n\n')
    },
    options: {
      persistentOutput: true
    }
  },
], {
  rendererOptions: { collapse: false }
});

tasks.run()
  .then(() => { })
  .catch(() => { });

Provide a way to run some code after the inner list finshes working

I've tried to simply run and await the inner Listr instance, but then the UI breaks.

new Listr([/* ... */, {
    title: 'Some task with inner list',
    task: async (_, task) => {
        try {
            await task.newListr([/* some tasks, one of them might fail */], {
                concurrent: true
            }).run();

            task.title += ' (success)';
        } catch (err) {
            task.title += ' (failed)';
            // plus some cleanup logic, to restore state of things before
            // the whole process started
        }
    }
}], {
    exitOnError: false,
});
CleanShot.2021-01-12.at.21.49.50.mp4

The repository with code producing above: https://github.com/erykpiast/listr2-callback

Duplicate lines

When executing Listr2 on Windows 10 with PowerShell there are some lines that are duplicated.

Here is the code

          const tasks = new Listr<any>([
            {
                title: 'Task1',
                task: () => jenkins.executeJobAndWaitForResultAsync(job)
            },
            {
                title: 'Task2',
                task: () => jenkins.executeJobAndWaitForResultAsync(job2)
            },

        ], {concurrent: false});

        tasks.run().catch((err) => {
            console.error(err);
        });

image

Skipping a Task with an active prompt

In one of my use cases, I would like the user to press a key if they want to interrupt the current task, otherwise continue on.

For example, I have an enquirer prompt that is something like the following Press any key to abort, otherwise continuing in 10 seconds...

However, when I skip the task while the prompt is active, the task get skipped but the prompt is still active in the background.

If I try to cancel the prompt, I always get hit with an error so that too exits the pipeline

    enquirer.on("prompt", async prompt => {
      await delay(10000);
      prompt.cancel();
    });

Lastly, if I try to skip the prompt with the built in skip function (which accepts a Promise<boolean> type), the prompt disappears into the background but is still active until it gets skipped

const status = await task.prompt({
    name: "continue",
    type: "input",
    message: `Press any key to abort, continuing in 10 seconds otherwise`,
    skip: async () => {
        await delay(10000);
        return true;
    }
});

What would be the appropriate approach for this pattern? I can make a contribution for it as well

[renovate-bot] Update Dependencies

This issue contains a list of Renovate updates and their statuses.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to ignore the schedule.

  • chore(deps): update all slow ring @Weekly [skip ci] (@types/jest, @types/node)

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Output does not wrap as it should

Using the following example:

const setupTasks = new Listr({
    title: 'Root Task',
    task: (ctx, task): Listr =>
        task.newListr(
            [
                {
                    options: { persistentOutput: true },
                    title: 'Sub task 1',
                    task: async (subCtx, subTask): Promise<void> => {
                        await CommonUtils.delay(2000);
                        subTask.output = 'PASSED: success message goes here';
                        return Promise.resolve();
                    }
                },
                {
                    options: { persistentOutput: true },
                    title: 'Sub task 2',
                    task: async (subCtx, subTask): Promise<void> => {
                        await CommonUtils.delay(1500);
                        subTask.output = 'FAILED: A very long error message goes here that should wrap but does not. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi auctor felis velit, sed imperdiet nisi venenatis nec. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris viverra lacus id lacus lobortis facilisis. Vivamus eu nisl eget lectus euismod ornare a vitae ex. Aliquam congue ultrices dictum. Mauris pretium quam nec nisl rutrum, et ornare dui viverra. Nulla pharetra faucibus ante, sed tempor sem pretium vel. Aliquam convallis ligula eu ex tristique ullamcorper. Morbi sollicitudin mauris tellus, in egestas sapien pharetra ac.';
                        return Promise.reject(new Error());
                    }
                },
                {
                    options: { persistentOutput: true },
                    title: 'Sub task 3',
                    task: async (subCtx, subTask): Promise<void> => {
                        await CommonUtils.delay(1000);
                        subTask.output = 'FAILED: Another long error message that should wrap but does not. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi auctor felis velit, sed imperdiet nisi venenatis nec. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris viverra lacus id lacus lobortis facilisis. Vivamus eu nisl eget lectus euismod ornare a vitae ex. Aliquam congue ultrices dictum. Mauris pretium quam nec nisl rutrum, et ornare dui viverra. Nulla pharetra faucibus ante, sed tempor sem pretium vel. Aliquam convallis ligula eu ex tristique ullamcorper. Morbi sollicitudin mauris tellus, in egestas sapien pharetra ac.';
                        return Promise.reject(new Error());
                    }
                }
            ],
            { concurrent: true, exitOnError: false, rendererOptions: { collapse: false, collapseErrors: false, formatOutput: 'wrap' } }
        )
});
try {
    await setupTasks.run();
} catch (error) {
    console.log(error);
}

Listr2 generates the following:

Screen Shot 2021-02-03 at 8 46 30 AM

But formatOutput: 'wrap' was set for rendererOptions so shouldn't the output messages be wrapped instead of truncated?

v2.6.0 is missing from https://replicate.npmjs.com/listr2

The latest version 2.6.0 of listr2 is not being replicated in npm - https://replicate.npmjs.com/listr2. It shows the latest version as 2.5.1. I just thought you should know

I have raised this with npm support but so far they all they have said is it can take a few hours to replicate, but this was published 11 days ago and counting

Since I am mirroring npm from replicate.npmjs.com, build processes are failing because other packages are relying on this version.

Display message from task underneath the task title

The original listr package displays the message from eg. skip underneath the task name.

Listr2 replaces the title with the message:

image

This leads to a bit of confusion, since the message is in the middle of task names and feels out of place. I didn't find an option to disable this. Is it possible for the renderer to print the skip messages indented and underneath:

image

I currently use this snippet to achieve this:

manager.add({
  title: 'Bump version',
  task: () => {
    if (shouldSkip === true) {
      return new Listr({
        title: "Doesn't matter",
        task: (_, task) => task.skip('Version has been already changed')
      }, { collapse: false })
    }
    return '...!'
  }
});

task-level exitOnError option

I have some tasks in my list that are ok to fail, and some that are not. I thought I could pass the exitOnError: false option to a task, but it appears that that option can only be passed while calling run.

This doesn't work, when encountering the error list exits

  const listr = new Listr(
    [
      {
        title: 'Allow fail',
        task: () => {
          throw new Error();
        },
        options: { exitOnError: false },
      },
    ];

As a workaround

  const listr = new Listr(
    [
      {
        title: 'Allow fail',
        task: (ctx, task) => {
          return task.newListr(
            [
              {
                task: () => {
                  throw new Error();
                },
              },
            ],
            { exitOnError: false }
          );
        },
      },
    ]

this works as desired, but is inconvenient. Is there another way?

task prompt function type does not contain previous prompt

I am trying to do a row of prompts and want one prompt to be skipped or of type text. The simplest solution for this is to use an if-statement with a previous prompt's response value, but the ctx does not contain the previous just the current prompt.

      ctx.version = await task.prompt([
        {
          type: 'select',
          name: 'version',
          message: 'New version',
          choices
        },
        {
          // prev contains only current prompt not from select version
          type: (prev) => (prev == 'custom' ? 'text' : null),
          name: 'version',
          message: 'Version',
          validate: validator,
        },
      ])

https://github.com/terkelg/prompts#-prompt-objects

How to use it with Ink

How can I use this with Ink ?
and when running on git bash, spinner is showing only line, it not showing rotating dots link in demo, and symbols are very small, is there a way to customize it ?

Execa streamed output support

Hey!

It would be very nice if listr2 would also have enquirer support just as the first version did. Currently it's possible to execute async commands and wait for them to complete, however streaming the output from them does not seem to be possible.

Example:

{
  title: "List files",
  task: (ctx) => {
    return execa.command(" ls -lah . && sleep 10 && ls -lah .");
  }
}

The command will execute successfully, however the output will not be streamed. I tried a bunch of different variations as well, but none were successful. The output is not being streamed to the console.

Help here would be much appreciated!

Icons doesn't work with cmd.exe

Hi,

As you can see in the picture, icons are not displaying correctly.

image

This happened on a WIndows 10 machine with System32\cmd.exe

Confusion between `NumberPrompt` vs `Numeral`

When trying to integrate Enquirer prompts for the first time It took some digging in your code to figure out how to get number prompts to work.

In your code you export a Numeral type.

https://github.com/cenk1cenk2/listr2/blob/1fbfaf27c2e3325855de73154689defabd679b0d/src/utils/prompt.interface.ts#L119

But in the enquirer docs they have a Markdown heading for a Numeral type (which is maybe where you got your naming from?) but the actual thing they export is a NumberPrompt:

https://github.com/enquirer/enquirer#numeral-prompt

I don't know why they have this confusion either.

Is it possible to help clear up the confusion to make this more discoverable? Or make Number an alias of Numeral? Perhaps also document here which types Listr2 works with?

https://listr2.kilic.dev/general-usage/user-input

Thanks!

feat: inserting and running sub-tasks dynamically

Problem

I'm creating a CLI to collect benchmarks, and I want to run a set of tasks n times. However, I don't want to create a new task for each one as n could be as high as 100.

Instead, I want to use one task that repeats it's sub-task n times, and updates the output message to Iteration ${i}.

Feature request

An API like this where I can insert/run arbitrary Listr instances dynamically at run-time:

const listr = new Listr<Options>([
	{
		title: 'Benchmarking',
		async task(context, task) {
			for (let i = 0; i < 10; i++) {
				task.output = `Iteration ${i}`;

				// Run arbitrary listr instances as a sub-task
				await task.run(task.newListr([
					{
						title: 'Task A',
						task() { ... }
					},
					{
						title: 'Task B',
						task() { ... }
					},
					{
						title: 'Task C',
						task() { ... }
					}
				]));
			}
		}
	},

	...
]);

Typings issue in v3.3.0

When using Listr2 in a TypeScript project I am getting the following TSC error when using v3.3.0:

../../node_modules/listr2/dist/lib/task-wrapper.d.ts:27:5 - error TS2416: Property 'run' in type 'TaskWrapper<Ctx, Renderer>' is not assignable to the same property in base type 'ListrTaskWrapper<Ctx, Renderer>'.
  Type '(ctx: Ctx) => Promise<void>' is not assignable to type '(ctx?: Ctx | undefined, task?: ListrTaskWrapper<Ctx, Renderer> | undefined) => Promise<void>'.
    Types of parameters 'ctx' and 'ctx' are incompatible.
      Type 'Ctx | undefined' is not assignable to type 'Ctx'.
        'Ctx' could be instantiated with an arbitrary type which could be unrelated to 'Ctx | undefined'.
          Type 'undefined' is not assignable to type 'Ctx'.
            'Ctx' could be instantiated with an arbitrary type which could be unrelated to 'undefined'.

27     run(ctx: Ctx): Promise<void>;

It compiles fine with the previous v3.2.3.

Thank you β™₯

This is a a big thank you for your efforts in developing this!

I was struggling to integrate listr in my company's publishing pipeline since it required custom inputs and then I came across listr2. Simply Awesome! Worked perfectly and the types are a huge bonus too. Not to mention the fast responses with fixing stray issues and bugs, I encountered along the way.

Just wanted to extend my thanks for this effort.

I hope more projects can benefit from your effort and this package in the future ❀️
Feel free to close this issue once you read it πŸ™‚

(if possible, leave it unlocked for other people to leave their own thank you's in the future πŸ˜‰)

Compiler errors when building

Hi, I am using Listr2 in a project and getting a bunch of errorrs from the declaration files that this library exports.

tsc -v Version 4.0.2

here is my tsconfig

{
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "declarationMap": true,
    "importHelpers": true,
    "module": "commonjs",
    "strict": true,
    "target": "es2017",
    "esModuleInterop": true,
    "lib": ["ESNext", "dom"],
    "sourceMap": true,
    "moduleResolution": "node",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "pretty": true
  },
  "exclude": [
    "node_modules",
    "**/*.test.ts"
  ],
  "include": [
    "src/**/*"
  ]
}

running tsc -b emits the errors below

@typerpc/cli:     The type 'readonly ListrTaskObject<any, ListrRendererFactory>[]' is 'readonly' and cannot be assigned to the mutable type 'ListrTaskObject<any, typeof DefaultRenderer>[]'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(30,45): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(31,47): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(32,44): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(33,52): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(34,41): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(35,44): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/silent.renderer.d.ts(3,33): error TS2344: Type 'typeof SilentRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Types of parameters 'tasks' and 'tasks' are incompatible.
@typerpc/cli:     The type 'readonly ListrTaskObject<any, ListrRendererFactory>[]' is 'readonly' and cannot be assigned to the mutable type 'ListrTaskObject<any, typeof SilentRenderer>[]'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/silent.renderer.d.ts(8,45): error TS2344: Type 'typeof SilentRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/verbose.renderer.d.ts(4,33): error TS2344: Type 'typeof VerboseRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Types of parameters 'tasks' and 'tasks' are incompatible.
@typerpc/cli:     The type 'readonly ListrTaskObject<any, ListrRendererFactory>[]' is 'readonly' and cannot be assigned to the mutable type 'ListrTaskObject<any, typeof VerboseRenderer>[]'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/verbose.renderer.d.ts(15,45): error TS2344: Type 'typeof VerboseRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(18,22): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Type 'typeof DefaultRenderer | (Renderer extends "verbose" ? typeof VerboseRenderer : Renderer extends "silent" ? typeof SilentRenderer : Renderer extends ListrRendererFactory ? Renderer : never)' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:     Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:       Type 'ListrRendererFactory | typeof DefaultRenderer | typeof VerboseRenderer | typeof SilentRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:         Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(19,48): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(21,31): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(21,99): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(109,33): error TS2344: Type 'typeof ListrBaseRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Types of parameters 'tasks' and 'tasks' are incompatible.
@typerpc/cli:     The type 'readonly ListrTaskObject<any, ListrRendererFactory>[]' is 'readonly' and cannot be assigned to the mutable type 'ListrTaskObject<any, typeof ListrBaseRenderer>[]'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(111,45): error TS2344: Type 'typeof ListrBaseRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(4,26): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Type 'typeof DefaultRenderer | (Renderer extends "verbose" ? typeof VerboseRenderer : Renderer extends "silent" ? typeof SilentRenderer : Renderer extends ListrRendererFactory ? Renderer : never)' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:     Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:       Type 'ListrRendererFactory | typeof DefaultRenderer | typeof VerboseRenderer | typeof SilentRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:         Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(4,85): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(6,22): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(13,38): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(13,97): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(14,30): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(14,89): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(9,54): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Type 'typeof DefaultRenderer | (Renderer extends "verbose" ? typeof VerboseRenderer : Renderer extends "silent" ? typeof SilentRenderer : Renderer extends ListrRendererFactory ? Renderer : never)' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:     Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:       Type 'ListrRendererFactory | typeof DefaultRenderer | typeof VerboseRenderer | typeof SilentRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:         Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(9,143): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(11,177): error TS2344: Type 'ListrGetRendererClassFromValue<InjectRenderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Type 'typeof DefaultRenderer | (InjectRenderer extends "verbose" ? typeof VerboseRenderer : InjectRenderer extends "silent" ? typeof SilentRenderer : InjectRenderer extends ListrRendererFactory ? InjectRenderer : never)' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:     Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:       Type 'ListrRendererFactory | typeof DefaultRenderer | typeof VerboseRenderer | typeof SilentRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:         Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(12,57): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(12,146): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(12,304): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(12,378): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(13,54): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.


@typerpc/cli:     The type 'readonly ListrTaskObject<any, ListrRendererFactory>[]' is 'readonly' and cannot be assigned to the mutable type 'ListrTaskObject<any, typeof DefaultRenderer>[]'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(30,45): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(31,47): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(32,44): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(33,52): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(34,41): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/default.renderer.d.ts(35,44): error TS2344: Type 'typeof DefaultRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/silent.renderer.d.ts(3,33): error TS2344: Type 'typeof SilentRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Types of parameters 'tasks' and 'tasks' are incompatible.
@typerpc/cli:     The type 'readonly ListrTaskObject<any, ListrRendererFactory>[]' is 'readonly' and cannot be assigned to the mutable type 'ListrTaskObject<any, typeof SilentRenderer>[]'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/silent.renderer.d.ts(8,45): error TS2344: Type 'typeof SilentRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/verbose.renderer.d.ts(4,33): error TS2344: Type 'typeof VerboseRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Types of parameters 'tasks' and 'tasks' are incompatible.
@typerpc/cli:     The type 'readonly ListrTaskObject<any, ListrRendererFactory>[]' is 'readonly' and cannot be assigned to the mutable type 'ListrTaskObject<any, typeof VerboseRenderer>[]'.
@typerpc/cli: ../../node_modules/listr2/dist/renderer/verbose.renderer.d.ts(15,45): error TS2344: Type 'typeof VerboseRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(18,22): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Type 'typeof DefaultRenderer | (Renderer extends "verbose" ? typeof VerboseRenderer : Renderer extends "silent" ? typeof SilentRenderer : Renderer extends ListrRendererFactory ? Renderer : never)' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:     Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:       Type 'ListrRendererFactory | typeof DefaultRenderer | typeof VerboseRenderer | typeof SilentRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:         Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(19,48): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(21,31): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(21,99): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(109,33): error TS2344: Type 'typeof ListrBaseRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Types of parameters 'tasks' and 'tasks' are incompatible.
@typerpc/cli:     The type 'readonly ListrTaskObject<any, ListrRendererFactory>[]' is 'readonly' and cannot be assigned to the mutable type 'ListrTaskObject<any, typeof ListrBaseRenderer>[]'.
@typerpc/cli: ../../node_modules/listr2/dist/interfaces/listr.interface.d.ts(111,45): error TS2344: Type 'typeof ListrBaseRenderer' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(4,26): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Type 'typeof DefaultRenderer | (Renderer extends "verbose" ? typeof VerboseRenderer : Renderer extends "silent" ? typeof SilentRenderer : Renderer extends ListrRendererFactory ? Renderer : never)' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:     Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:       Type 'ListrRendererFactory | typeof DefaultRenderer | typeof VerboseRenderer | typeof SilentRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:         Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(4,85): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(6,22): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(13,38): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(13,97): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(14,30): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/listr.d.ts(14,89): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(9,54): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Type 'typeof DefaultRenderer | (Renderer extends "verbose" ? typeof VerboseRenderer : Renderer extends "silent" ? typeof SilentRenderer : Renderer extends ListrRendererFactory ? Renderer : never)' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:     Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:       Type 'ListrRendererFactory | typeof DefaultRenderer | typeof VerboseRenderer | typeof SilentRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:         Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(9,143): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(11,177): error TS2344: Type 'ListrGetRendererClassFromValue<InjectRenderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli:   Type 'typeof DefaultRenderer | (InjectRenderer extends "verbose" ? typeof VerboseRenderer : InjectRenderer extends "silent" ? typeof SilentRenderer : InjectRenderer extends ListrRendererFactory ? InjectRenderer : never)' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:     Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:       Type 'ListrRendererFactory | typeof DefaultRenderer | typeof VerboseRenderer | typeof SilentRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli:         Type 'typeof DefaultRenderer' is not assignable to type 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(12,57): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(12,146): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(12,304): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(12,378): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.
@typerpc/cli: ../../node_modules/listr2/dist/manager.d.ts(13,54): error TS2344: Type 'ListrGetRendererClassFromValue<Renderer>' does not satisfy the constraint 'ListrRendererFactory'.

Feature Request: Retry on Error

For example,

async function main (): Promise<void> {
  await new Listr([
    {
      task: (ctx, task) => {       // line #4
        return (
          execa.command(`xyz -y`)
               .then(()=> // do something)
               .catch((err: any) => {
                 // e.g. the user doesn't have `xyz` installed or accessible
                 if (err.code === 'ENOENT') {
                   npm install xyz // <---- address specific error
                   task.retry(1)   // <---- rerun the current task, e.g. the
                                   //       task starting on line 4 of this
                                   //       example;
                                   //       to avoid infinite loops, pass a
                                   //       maximum number of retries, e.g. `1`;
                                   //       should probably default to `1`
                      }
                   }))
    }
    ], {}
  ).run()
}

Capture `stdin` with `execa` to run interactive suprocesses

Hi,

First of all, thanks for maintaining this project πŸ™ !

As part of one of my tasks, I'd like to execute npm init svelte@next -y. The challenge I run into is that the npm init script is interactive and displays a number of prompts.

My task currently looks like this:

const initWebApp = (ctx: Ctx, task: WebstoneTask) => {
  ctx.webAppDir = `${ctx.appDir}/services/web`;

  fs.removeSync(`${ctx.webAppDir}/.keep`);

  const svelteSubprocess = execa("npm init -y svelte@next", {
    cwd: ctx.webAppDir,
    shell: true,
    stdio: "inherit",
  });
  // svelteSubprocess.stdout.pipe(task.stdout())
  return svelteSubprocess;
};

If I comment out the line above the return statement, the task fails with TypeError: Cannot read property pipe of null, which makes sense. The subprocess then executes, but any tasks defined afterwards fail, which also makes sense.

Is it possible to capture a user's input to that subprocess and once the subprocess completed, continue with the next task in my list?

exitOnError swallows output

According to the docs:

// it will collect all the errors encountered if { exitOnError: false } is set as an option
// elsewise it will throw the first error encountered as expected

In practice:

  new Listr(
    [
      {
        title: 'fail',
        task: () => {
          throw new Error('fail');
        },
      },
    ],
    { exitOnError: false }
  )
    .run()
    .catch((e) => console.error('in catch', e))

If exitOnError: false is set, the catch is never triggered.

Exception (`string` and `indent` should be strings in v1.3.5)

The new version 1.3.5 throws the following error on running:
'string' and 'indent' should be strings

Stacktrace
/abc/node_modules/indent-string/index.js:6
                throw new TypeError('`string` and `indent` should be strings');
                ^

TypeError: string and indent should be strings
at Object.module.exports [as default] (/abc/node_modules/indent-string/index.js:6:9)
at MultiLineRenderer.formatString (/abc/node_modules/listr2/dist/renderer/default.renderer.js:125:42)
at MultiLineRenderer.multiLineRenderer (/abc/node_modules/listr2/dist/renderer/default.renderer.js:51:38)
at MultiLineRenderer.multiLineRenderer (/abc/node_modules/listr2/dist/renderer/default.renderer.js:81:48)
at Timeout._onTimeout (/abc/node_modules/listr2/dist/renderer/default.renderer.js:25:39)
at listOnTimeout (internal/timers.js:536:17)
at processTimers (internal/timers.js:480:7)

Specs

  • Version: 1.3.5
  • Node: 13.3.0

[Regression] Promise rejections are handled, but task is removed from list

Current Behavior

In Listr, rejected promises and thrown errors are displayed in the list, but they remain uncaught. Listr2 appears to have fixed the issue by handling errors; however, tasks that return a rejected promise are removed from the task list, and thrown errors overwrite the task title.
This example on Repl.it demonstrates the described behavior.

Expected Behavior

  • Tasks are never removed from list, mimicking the behavior of Listr.
  • Error message is displayed as task output, mimicking the behavior of Listr.
  • Rejected promises display error messages or strings as task output.

Proposed Behavior

Having task titles overwritten by default is a poor design choice from a UX perspective, be it from errors or skipping.

  • Add an overwriteTitles key to rendererOptions, that controls this behavior.
  • Error and skip messages should be displayed as output by default.
    • This will not be a breaking change, as the current behavior is already a breaking change from the expected output.
  • Rejected promises display error messages or strings as task output.

ListrRenderer and ListrTaskObject are not imported

'Custom Renderers' documentations says that user have to do following:

import { ListrRenderer, ListrTaskObject } from 'listr2

but actual result is:

> require('listr2')
{ Listr: [Function: Listr],
  Manager: [Function: Manager],
  ListrError: [Function: ListrError],
  PromptError: [Function: PromptError],
  Logger: [Function: Logger],
  logLevels:
   { silent: 'silent',
     fail: 'fail',
     skip: 'skip',
     success: 'success',
     data: 'data',
     start: 'start',
     title: 'title' },
  newPrompt: [Function: newPrompt],
  createPrompt: [Function: createPrompt] }

Can you fix it, please? It will allow users to create custom loggers and etc.

The automated release is failing 🚨

🚨 The automated release from the alpha branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the alpha branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid npm token.

The npm token configured in the NPM_TOKEN environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/.

If you are using Two-Factor Authentication, make configure the auth-only level is supported. semantic-release cannot publish with the default auth-and-writes level.

Please make sure to set the NPM_TOKEN environment variable in your CI with the exact value of the npm token.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

breaking change on `rxjs` upgrade

Hi, we notice the rxjs upgrade in version 3.8.3, this could leading to some reference error if other modules import rxjs@6. A breaking change is recommended if you guys need to upgrade rxjs to 7.

Content is printed twice

I have the following sample code:

const setupTasks = new Listr({
    title: 'Root Task',
    task: (ctx, task): Listr =>
        task.newListr(
            [
                {
                    options: { persistentOutput: true },
                    title: 'Sub task 1',
                    task: async (subCtx, subTask): Promise<void> => {
                        await delay(3000);
                        subTask.output = 'Output for sub task 1';
                        return Promise.resolve();
                    }
                },
                {
                    options: { persistentOutput: true },
                    title: 'Sub task 2',
                    task: async (subCtx, subTask): Promise<void> => {
                        await delay(2000);
                        subTask.output = 'Error message for sub task 2';
                        return Promise.reject();
                    }
                },
                {
                    options: { persistentOutput: true },
                    title: 'Sub task 3',
                    task: async (subCtx, subTask): Promise<void> => {
                        await delay(1000);
                        subTask.output = 'Error message for sub task 3';
                        return Promise.reject();
                    }
                }
            ],
            { concurrent: true, exitOnError: false, rendererOptions: { collapse: false, collapseErrors: false } }
        )
});

try {
    await setupTasks.run();
} catch (error) {
    console.log(error);
}

When I run this sample, I see that Listr prints the output twice as tasks progress:

Screen Shot 2021-02-01 at 3 44 39 PM

Is there a way to work around this issue to have the result printed only once?

If subtask in concurrent mode fails, the renderer gets stuck and fails silently

If a subtask throws an error in concurrent mode the renderer stops animating the rest of the subtasks. No error is printed and listr2 fails silently. Not sure if I have to use manager.indent for this to work.

const manager = new Manager();

manager.add({
  title: 'Do stuff',
  task: async () => {
    return new Listr([
      { title: 'Task 1', task: async () => { throw new Error('FAIL') } },
      { title: 'Task 2', task: async () => { await delay(1000); return true; } }
    ], { concurrent: true })
  }
});

manager.runAll().catch(() => null);

listr2-bug

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.