@slimio/async-cli-spinner

Asynchronous CLI Spinner. Allow to create and manage simultaneous/multiple spinners at a time.

Usage no npm install needed!

<script type="module">
  import slimioAsyncCliSpinner from 'https://cdn.skypack.dev/@slimio/async-cli-spinner';
</script>

README

Async-cli-spinner

version Maintenance MIT dep size Known Vulnerabilities Build Status Greenkeeper badge

Asynchronous CLI Spinner. This package has been created to handle simultaneous/multiple spinner at a time. The package has been inspired by Ora but in Asynchronous.

All available spinners are part of cli-spinners package.

Requirements

Getting Started

This package is available in the Node Package Repository and can be easily installed with npm or yarn.

$ npm i @slimio/async-cli-spinner
# or
$ yarn add @slimio/async-cli-spinner

Usage example

Create and wait multiple spinner at a time.

const { promisify } = require("util");
const Spinner = require("@slimio/async-cli-spinner");

const sleep = promisify(setTimeout);

async function fnWithSpinner(prefixText, succeed = true) {
    const spinner = new Spinner({ prefixText }).start("Start working!");

    await sleep(1000);
    spinner.text = "Work in progress...";
    await sleep(1000);

    if (succeed) {
        spinner.succeed(`All done in ${spinner.elapsedTime.toFixed(2)}ms !`);
    }
    else {
        spinner.failed("Something wrong happened !");
    }
}

Spinner.startAll([
    fnWithSpinner,
    Spinner.create(fnWithSpinner),
    Spinner.create(fnWithSpinner, "Item 1"),
    Spinner.create(fnWithSpinner, "Item 2", false)
])
.then(() => console.log("All spinners finished!"))
.catch(console.error);

If you want to only achieve one Spinner by one Spinner, use it like Ora (it will work)

const spinner = new Spinner().start("Start working!");

await sleep(1000);
spinner.text = "Work in progress...";

await sleep(1000);
spinner.succeed("All done !");

👀 When you are working on a CLI that can be used as an API too, the verbose option allow you to disable the Spinner.

API

Spinner line structure : ${spinner} ${prefixText} - ${text}

Properties :

declare namespace Spinner {
    public spinner: cliSpinners.Spinner;
    public prefixText: string;
    public text: string;
    public color: string;
    public started: boolean;
    public startTime: number;
    public stream: TTY.WriteStream;
    public readonly elapsedTime: number;
}
  • spinner: spinner type (default: "dots")
  • prefixText: mostly used to differentiate each spinner
  • text: you can change text at any moment.
  • color: spinner color
  • elapsedTime: time elapsed since start() call
constructor(options?: Spinner.options)

Create a new Spinner object. options is described by the following TypeScript interface:

declare namespace Spinner {
    interface spinnerObj {
        frames: string[];
        interval: number;
    }

    interface options {
        spinner: SpinnerObj | Spinner.spinners;
        text: string;
        prefixText: string;
        color: string;
        verbose: boolean;
    }
}

👀 Look cli-spinners for all kind of available spinners.

Example:

const Spinner = require("@slimio/async-cli-spinner");

const spinner = new Spinner();
const dotsSpinner = new Spinner({ spinner: "dots" });
static startAll(functions: Spinner.Handler[], options?: Spinner.startOpt): Promise<any[]>
Start all functions with spinners passed in array.

⚠️ Only accept functions that return a Promise.

Options is described by the following TypeScript interface:

declare namespace Spinner {
    type RecapSet = "none" | "error" | "always";

    interface startOpt {
        recap: RecapSet;
        rejects: boolean;
    }
}

Default recap : always

static create(fn: Spinner.Handler, args?: any): Function|[Function, ...any]
This method allow to pass arguments to our spinner function. This method prevent execute function to earlier.
async function fnWithSpinner(prefixText) {
    const spinner = new Spinner({ prefixText }).start("Start working!");

    await new Promise((resolve) => setTimeout(resolve, 1000));
    spinner.text = "Work in progress...";

    await new Promise((resolve) => setTimeout(resolve, 1000));
    spinner.succeed("All done !");
}

Spinner.startAll([
    fnWithSpinner("Item 1"), // <-- Wrong, it's executed directly, not in startAll
    Spinner.create(fnWithSpinner, "Item 2") // <-- What you should do
])
.then(() => console.log("All spinners finished!"))
.catch(console.error);

start(text?: string): Spinner

Start the spinner in the CLI and write the text passed in param.

const Spinner = require("@slimio/async-cli-spinner");

async function fnWithSpinner() {
    const spinner = new Spinner().start("Start working!");
}

Spinner.startAll([
    fnWithSpinner
])
.then(() => console.log("All spinners finished!"))
.catch(console.error);
succeed(text?: string): void

Stop the spinner in the CLI, write the text passed in param and mark it as succeed with a symbol.

const Spinner = require("@slimio/async-cli-spinner");

async function fnWithSpinner() {
    const spinner = new Spinner().start("Start working!");

    await new Promise((resolve) => setTimeout(resolve, 1000));
    spinner.succeed("All done !");
}

Spinner.startAll([
    fnWithSpinner
])
.then(() => console.log("All spinners finished!"))
.catch(console.error);
failed(text?: string): void

Stop the spinner in the CLI, write the text passed in param and mark it as failed with a symbol.

const Spinner = require("@slimio/async-cli-spinner");

async function fnWithSpinner() {
    const spinner = new Spinner().start("Start working!");

    await new Promise((resolve) => setTimeout(resolve, 1000));
    spinner.failed("Something wrong happened !");
}

Spinner.startAll([
    fnWithSpinner
])
.then(() => console.log("All spinners finished!"))
.catch(console.error);

⚠️ Functions start(), succeed() and failed() are supposed to be executed in a function which return a promise and will be called by Spinner.startAll().

Dependencies

Name Refactoring Security Risk Usage
@slimio/is Minor Low Type checker
@slimio/wcwidth ⚠️Major Low Get CLI columns for special characters
ansi-regex Minor Low Get ANSI code
cli-cursor ⚠️Major High Show/Hide CLI cursor
cli-spinners Minor Low Bunch of spinner
kleur Minor Low CLI color
strip-ansi Minor Low ANSI escape codes

License

MIT