diff --git a/.github/funding.yml b/.github/funding.yml deleted file mode 100644 index 15edf6e..0000000 --- a/.github/funding.yml +++ /dev/null @@ -1,4 +0,0 @@ -github: sindresorhus -open_collective: sindresorhus -patreon: sindresorhus -custom: https://sindresorhus.com/donate diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c1870cf..441975c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,12 +10,10 @@ jobs: fail-fast: false matrix: node-version: - - 14 - - 12 - - 10 + - 16 steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - run: npm install diff --git a/example.js b/example.js index 9d04be3..f782a5f 100644 --- a/example.js +++ b/example.js @@ -1,16 +1,16 @@ -'use strict'; -const chalk = require('chalk'); -const Ora = require('.'); +import process from 'node:process'; +import chalk from 'chalk'; +import ora from './index.js'; -const spinner = new Ora({ +const spinner = ora({ discardStdin: false, text: 'Loading unicorns, not discarding stdin', - spinner: process.argv[2] + spinner: process.argv[2], }); -const spinnerDiscardingStdin = new Ora({ +const spinnerDiscardingStdin = ora({ text: 'Loading unicorns', - spinner: process.argv[2] + spinner: process.argv[2], }); spinnerDiscardingStdin.start(); diff --git a/index.d.ts b/index.d.ts index 62174e6..b35bba4 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,293 +1,294 @@ import {SpinnerName} from 'cli-spinners'; -declare namespace ora { - interface Spinner { - readonly interval?: number; - readonly frames: string[]; - } +export interface Spinner { + readonly interval?: number; + readonly frames: string[]; +} + +export type Color = + | 'black' + | 'red' + | 'green' + | 'yellow' + | 'blue' + | 'magenta' + | 'cyan' + | 'white' + | 'gray'; - type Color = - | 'black' - | 'red' - | 'green' - | 'yellow' - | 'blue' - | 'magenta' - | 'cyan' - | 'white' - | 'gray'; +export type PrefixTextGenerator = () => string; - type PrefixTextGenerator = () => string; +export interface Options { + /** + Text to display after the spinner. + */ + readonly text?: string; - interface Options { - /** - Text to display after the spinner. - */ - readonly text?: string; + /** + Text or a function that returns text to display before the spinner. No prefix text will be displayed if set to an empty string. + */ + readonly prefixText?: string | PrefixTextGenerator; - /** - Text or a function that returns text to display before the spinner. No prefix text will be displayed if set to an empty string. - */ - readonly prefixText?: string | PrefixTextGenerator; + /** + Name of one of the provided spinners. See [`example.js`](https://github.com/BendingBender/ora/blob/main/example.js) in this repo if you want to test out different spinners. On Windows, it will always use the line spinner as the Windows command-line doesn't have proper Unicode support. - /** - Name of one of the provided spinners. See [`example.js`](https://github.com/BendingBender/ora/blob/main/example.js) in this repo if you want to test out different spinners. On Windows, it will always use the line spinner as the Windows command-line doesn't have proper Unicode support. + @default 'dots' - @default 'dots' + Or an object like: - Or an object like: + @example + ``` + { + interval: 80, // Optional + frames: ['-', '+', '-'] + } + ``` + */ + readonly spinner?: SpinnerName | Spinner; - @example - ``` - { - interval: 80, // Optional - frames: ['-', '+', '-'] - } - ``` - */ - readonly spinner?: SpinnerName | Spinner; + /** + Color of the spinner. - /** - Color of the spinner. + @default 'cyan' + */ + readonly color?: Color; - @default 'cyan' - */ - readonly color?: Color; + /** + Set to `false` to stop Ora from hiding the cursor. - /** - Set to `false` to stop Ora from hiding the cursor. + @default true + */ + readonly hideCursor?: boolean; - @default true - */ - readonly hideCursor?: boolean; + /** + Indent the spinner with the given number of spaces. - /** - Indent the spinner with the given number of spaces. + @default 0 + */ + readonly indent?: number; - @default 0 - */ - readonly indent?: number; + /** + Interval between each frame. - /** - Interval between each frame. + Spinners provide their own recommended interval, so you don't really need to specify this. - Spinners provide their own recommended interval, so you don't really need to specify this. + Default: Provided by the spinner or `100`. + */ + readonly interval?: number; - Default: Provided by the spinner or `100`. - */ - readonly interval?: number; + /** + Stream to write the output. - /** - Stream to write the output. + You could for example set this to `process.stdout` instead. - You could for example set this to `process.stdout` instead. + @default process.stderr + */ + readonly stream?: NodeJS.WritableStream; - @default process.stderr - */ - readonly stream?: NodeJS.WritableStream; + /** + Force enable/disable the spinner. If not specified, the spinner will be enabled if the `stream` is being run inside a TTY context (not spawned or piped) and/or not in a CI environment. - /** - Force enable/disable the spinner. If not specified, the spinner will be enabled if the `stream` is being run inside a TTY context (not spawned or piped) and/or not in a CI environment. + Note that `{isEnabled: false}` doesn't mean it won't output anything. It just means it won't output the spinner, colors, and other ansi escape codes. It will still log text. + */ + readonly isEnabled?: boolean; - Note that `{isEnabled: false}` doesn't mean it won't output anything. It just means it won't output the spinner, colors, and other ansi escape codes. It will still log text. - */ - readonly isEnabled?: boolean; + /** + Disable the spinner and all log text. All output is suppressed and `isEnabled` will be considered `false`. - /** - Disable the spinner and all log text. All output is suppressed and `isEnabled` will be considered `false`. + @default false + */ + readonly isSilent?: boolean; - @default false - */ - readonly isSilent?: boolean; + /** + Discard stdin input (except Ctrl+C) while running if it's TTY. This prevents the spinner from twitching on input, outputting broken lines on `Enter` key presses, and prevents buffering of input while the spinner is running. - /** - Discard stdin input (except Ctrl+C) while running if it's TTY. This prevents the spinner from twitching on input, outputting broken lines on `Enter` key presses, and prevents buffering of input while the spinner is running. + This has no effect on Windows as there's no good way to implement discarding stdin properly there. - This has no effect on Windows as there's no good way to implement discarding stdin properly there. + @default true + */ + readonly discardStdin?: boolean; +} - @default true - */ - readonly discardStdin?: boolean; - } +export interface PersistOptions { + /** + Symbol to replace the spinner with. - interface PersistOptions { - /** - Symbol to replace the spinner with. + @default ' ' + */ + readonly symbol?: string; - @default ' ' - */ - readonly symbol?: string; + /** + Text to be persisted after the symbol. - /** - Text to be persisted after the symbol. + Default: Current `text`. + */ + readonly text?: string; - Default: Current `text`. - */ - readonly text?: string; + /** + Text or a function that returns text to be persisted before the symbol. No prefix text will be displayed if set to an empty string. - /** - Text or a function that returns text to be persisted before the symbol. No prefix text will be displayed if set to an empty string. + Default: Current `prefixText`. + */ + readonly prefixText?: string | PrefixTextGenerator; +} - Default: Current `prefixText`. - */ - readonly prefixText?: string | PrefixTextGenerator; - } +export interface PromiseOptions extends Options { + /** + The new text of the spinner when the promise is resolved. - interface PromiseOptions extends Options { - /** - The new text of the spinner when the promise is resolved. + Keeps the existing text if `undefined`. + */ + successText?: string | ((result: T) => string) | undefined; - If undefined, will keep the initial text. - */ - successText?: string | ((result: T) => string); + /** + The new text of the spinner when the promise is rejected. - /** - The new text of the spinner when the promise is rejected. + Keeps the existing text if `undefined`. + */ + failText?: string | ((error: Error) => string) | undefined; +} - If undefined, will keep the initial text. - */ - failText?: string | ((error: Error) => string); - } +export interface Ora { + /** + A boolean of whether the instance is currently spinning. + */ + readonly isSpinning: boolean; - interface Ora { - /** - A boolean of whether the instance is currently spinning. - */ - readonly isSpinning: boolean; + /** + Change the text after the spinner. + */ + text: string; - /** - Change the text after the spinner. - */ - text: string; + /** + Change the text or function that returns text before the spinner. No prefix text will be displayed if set to an empty string. + */ + prefixText: string | PrefixTextGenerator; - /** - Change the text or function that returns text before the spinner. No prefix text will be displayed if set to an empty string. - */ - prefixText: string | PrefixTextGenerator; + /** + Change the spinner color. + */ + color: Color; - /** - Change the spinner color. - */ - color: Color; + /** + Change the spinner. + */ + spinner: SpinnerName | Spinner; - /** - Change the spinner. - */ - spinner: SpinnerName | Spinner; + /** + Change the spinner indent. + */ + indent: number; - /** - Change the spinner indent. - */ - indent: number; + /** + Start the spinner. - /** - Start the spinner. + @param text - Set the current text. + @returns The spinner instance. + */ + start(text?: string): Ora; - @param text - Set the current text. - @returns The spinner instance. - */ - start(text?: string): Ora; + /** + Stop and clear the spinner. - /** - Stop and clear the spinner. + @returns The spinner instance. + */ + stop(): Ora; - @returns The spinner instance. - */ - stop(): Ora; + /** + Stop the spinner, change it to a green `✔` and persist the current text, or `text` if provided. - /** - Stop the spinner, change it to a green `✔` and persist the current text, or `text` if provided. + @param text - Will persist text if provided. + @returns The spinner instance. + */ + succeed(text?: string): Ora; - @param text - Will persist text if provided. - @returns The spinner instance. - */ - succeed(text?: string): Ora; + /** + Stop the spinner, change it to a red `✖` and persist the current text, or `text` if provided. - /** - Stop the spinner, change it to a red `✖` and persist the current text, or `text` if provided. + @param text - Will persist text if provided. + @returns The spinner instance. + */ + fail(text?: string): Ora; - @param text - Will persist text if provided. - @returns The spinner instance. - */ - fail(text?: string): Ora; + /** + Stop the spinner, change it to a yellow `⚠` and persist the current text, or `text` if provided. - /** - Stop the spinner, change it to a yellow `⚠` and persist the current text, or `text` if provided. + @param text - Will persist text if provided. + @returns The spinner instance. + */ + warn(text?: string): Ora; - @param text - Will persist text if provided. - @returns The spinner instance. - */ - warn(text?: string): Ora; + /** + Stop the spinner, change it to a blue `ℹ` and persist the current text, or `text` if provided. - /** - Stop the spinner, change it to a blue `ℹ` and persist the current text, or `text` if provided. + @param text - Will persist text if provided. + @returns The spinner instance. + */ + info(text?: string): Ora; - @param text - Will persist text if provided. - @returns The spinner instance. - */ - info(text?: string): Ora; + /** + Stop the spinner and change the symbol or text. - /** - Stop the spinner and change the symbol or text. + @returns The spinner instance. + */ + stopAndPersist(options?: PersistOptions): Ora; - @returns The spinner instance. - */ - stopAndPersist(options?: PersistOptions): Ora; + /** + Clear the spinner. - /** - Clear the spinner. + @returns The spinner instance. + */ + clear(): Ora; - @returns The spinner instance. - */ - clear(): Ora; + /** + Manually render a new frame. - /** - Manually render a new frame. + @returns The spinner instance. + */ + render(): Ora; - @returns The spinner instance. - */ - render(): Ora; + /** + Get a new frame. - /** - Get a new frame. - - @returns The spinner instance text. - */ - frame(): string; - } + @returns The spinner instance text. + */ + frame(): string; } -declare const ora: { - /** - Elegant terminal spinner. +/** +Elegant terminal spinner. - @param options - If a string is provided, it is treated as a shortcut for `options.text`. +@param options - If a string is provided, it is treated as a shortcut for `options.text`. - @example - ``` - import ora = require('ora'); +@example +``` +import ora from 'ora'; - const spinner = ora('Loading unicorns').start(); +const spinner = ora('Loading unicorns').start(); - setTimeout(() => { - spinner.color = 'yellow'; - spinner.text = 'Loading rainbows'; - }, 1000); - ``` - */ - (options?: string | ora.Options): ora.Ora; +setTimeout(() => { + spinner.color = 'yellow'; + spinner.text = 'Loading rainbows'; +}, 1000); +``` +*/ +export default function ora(options?: string | Options): Ora; - /** - Starts a spinner for a function or a promise. The spinner is stopped with `.succeed()` if the promise fulfills or with `.fail()` if it rejects. Returns the Promise. +/** +Starts a spinner for a promise or promise-returning function. The spinner is stopped with `.succeed()` if the promise fulfills or with `.fail()` if it rejects. - @param action - The promise to start the spinner for. - @param options - If a string is provided, it is treated as a shortcut for `options.text`. - @returns The spinner instance. - */ - promise( - action: PromiseLike | ((spinner: ora.Ora) => PromiseLike), - options?: string | ora.PromiseOptions - ): Promise; -}; +@param action - The promise to start the spinner for or a promise-returning function. +@param options - If a string is provided, it is treated as a shortcut for `options.text`. +@returns The given promise. + +@example +``` +import {oraPromise} from 'ora'; -export = ora; +await oraPromise(somePromise); +``` +*/ +export function oraPromise( + action: PromiseLike | ((spinner: Ora) => PromiseLike), + options?: string | PromiseOptions +): Promise; diff --git a/index.js b/index.js index af99dff..cd99162 100644 --- a/index.js +++ b/index.js @@ -1,19 +1,21 @@ -'use strict'; -const readline = require('readline'); -const chalk = require('chalk'); -const cliCursor = require('cli-cursor'); -const cliSpinners = require('cli-spinners'); -const logSymbols = require('log-symbols'); -const stripAnsi = require('strip-ansi'); -const wcwidth = require('wcwidth'); -const isInteractive = require('is-interactive'); -const isUnicodeSupported = require('is-unicode-supported'); -const {BufferListStream} = require('bl'); +import process from 'node:process'; +import readline from 'node:readline'; +import chalk from 'chalk'; +import cliCursor from 'cli-cursor'; +import cliSpinners from 'cli-spinners'; +import logSymbols from 'log-symbols'; +import stripAnsi from 'strip-ansi'; +import wcwidth from 'wcwidth'; +import isInteractive from 'is-interactive'; +import isUnicodeSupported from 'is-unicode-supported'; +import {BufferListStream} from 'bl'; const TEXT = Symbol('text'); const PREFIX_TEXT = Symbol('prefixText'); const ASCII_ETX_CODE = 0x03; // Ctrl+C emits this code +// TODO: Use class fields when ESLint 8 is out. + class StdinDiscarder { constructor() { this.requests = 0; @@ -68,7 +70,7 @@ class StdinDiscarder { this.rl = readline.createInterface({ input: process.stdin, - output: this.mutedStream + output: this.mutedStream, }); this.rl.on('SIGINT', () => { @@ -101,7 +103,7 @@ class Ora { if (typeof options === 'string') { options = { - text: options + text: options, }; } @@ -110,7 +112,7 @@ class Ora { color: 'cyan', stream: process.stderr, discardStdin: true, - ...options + ...options, }; this.spinner = this.options.spinner; @@ -267,8 +269,8 @@ class Ora { this.stream.cursorTo(0); - for (let i = 0; i < this.linesToClear; i++) { - if (i > 0) { + for (let index = 0; index < this.linesToClear; index++) { + if (index > 0) { this.stream.moveCursor(0, -1); } @@ -280,7 +282,6 @@ class Ora { } this.lastIndent = this.indent; - this.linesToClear = 0; return this; @@ -387,14 +388,11 @@ class Ora { } } -const oraFactory = function (options) { +export default function ora(options) { return new Ora(options); -}; - -module.exports = oraFactory; +} -// https://github.com/sindresorhus/ora/issues/169#issuecomment-873269524 -module.exports.promise = async (action, options) => { +export async function oraPromise(action, options) { const actionIsFunction = typeof action === 'function'; // eslint-disable-next-line promise/prefer-await-to-then const actionIsPromise = typeof action.then === 'function'; @@ -403,25 +401,30 @@ module.exports.promise = async (action, options) => { throw new TypeError('Parameter `action` must be a Function or a Promise'); } - const {successText, failText} = typeof options === 'object' ? - options : - {successText: undefined, failText: undefined}; + const {successText, failText} = typeof options === 'object' + ? options + : {successText: undefined, failText: undefined}; + + const spinner = ora(options).start(); - const spinner = new Ora(options); // Set the initial string or ora options. - spinner.start(); try { const promise = actionIsFunction ? action(spinner) : action; const result = await promise; - spinner.succeed(successText === undefined ? - undefined : - (typeof successText === 'string' ? successText : successText(result)) + + spinner.succeed( + successText === undefined + ? undefined + : (typeof successText === 'string' ? successText : successText(result)), ); + return result; } catch (error) { - spinner.fail(failText === undefined ? - undefined : - (typeof failText === 'string' ? failText : failText(error)) + spinner.fail( + failText === undefined + ? undefined + : (typeof failText === 'string' ? failText : failText(error)), ); + throw error; } -}; +} diff --git a/index.test-d.ts b/index.test-d.ts index f238b8a..5c129c0 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,7 +1,6 @@ +import {PassThrough as PassThroughStream} from 'node:stream'; import {expectType} from 'tsd'; -import {PassThrough as PassThroughStream} from 'stream'; -import ora = require('./index.js'); -import {promise} from './index.js'; +import ora, {oraPromise} from './index.js'; const spinner = ora('Loading unicorns'); ora({text: 'Loading unicorns'}); @@ -45,18 +44,18 @@ spinner.render(); spinner.frame(); const resolves = Promise.resolve(1); -void promise(resolves, 'foo'); -void promise(resolves, { +void oraPromise(resolves, 'foo'); +void oraPromise(resolves, { stream: new PassThroughStream(), text: 'foo', color: 'blue', isEnabled: true, - isSilent: false + isSilent: false, }); -void promise(async () => { +void oraPromise(async () => { await resolves; }, 'foo'); -void promise(async spinner => { +void oraPromise(async spinner => { spinner.prefixText = 'foo'; await resolves; return 7; @@ -67,5 +66,5 @@ void promise(async spinner => { isEnabled: true, isSilent: false, successText: result => `Resolved with number ${result}`, - failText: 'bar' + failText: 'bar', }); diff --git a/package.json b/package.json index 323c489..dad0be5 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ "email": "sindresorhus@gmail.com", "url": "https://sindresorhus.com" }, + "type": "module", + "exports": "./index.js", "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "scripts": { "test": "xo && ava && tsd" @@ -37,22 +39,22 @@ "idle" ], "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", + "bl": "^5.0.0", + "chalk": "^4.1.2", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.6.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.1.0", + "log-symbols": "^5.0.0", + "strip-ansi": "^7.0.0", "wcwidth": "^1.0.1" }, "devDependencies": { - "@types/node": "^14.14.35", - "ava": "^2.4.0", - "get-stream": "^6.0.0", + "@types/node": "^16.7.1", + "ava": "^3.15.0", + "get-stream": "^6.0.1", "transform-tty": "^1.0.11", - "tsd": "^0.14.0", - "xo": "^0.38.2" + "tsd": "^0.17.0", + "xo": "^0.44.0" } } diff --git a/readme.md b/readme.md index ae4cd52..eae7e71 100644 --- a/readme.md +++ b/readme.md @@ -17,7 +17,7 @@ $ npm install ora ## Usage ```js -const ora = require('ora'); +import ora from 'ora'; const spinner = ora('Loading unicorns').start(); @@ -223,10 +223,16 @@ Change the spinner. Change the spinner indent. -### ora.promise(action, text) -### ora.promise(action, options) +### oraPromise(action, text) +### oraPromise(action, options) -Starts a spinner for a function or a promise. The spinner is stopped with `.succeed()` if the promise fulfills or with `.fail()` if it rejects. Returns the promise. +Starts a spinner for a promise or promise-returning function. The spinner is stopped with `.succeed()` if the promise fulfills or with `.fail()` if it rejects. Returns the promise. + +```js +import {oraPromise} from 'ora'; + +await oraPromise(somePromise); +``` #### action @@ -239,15 +245,20 @@ Type: `object` All of the [options](#options) plus the following: ##### successText -Type: `string | ((result: T) => string)` -The new text of the spinner when the promise is resolved. If undefined, will keep the initial text. +Type: `string | ((result: T) => string) | undefined` + +The new text of the spinner when the promise is resolved. + +Keeps the existing text if `undefined`. ##### failText -Type: `string | ((error: Error) => string)` -The new text of the spinner when the promise is rejected. If undefined, will keep the initial text. +Type: `string | ((error: Error) => string) | undefined` + +The new text of the spinner when the promise is rejected. +Keeps the existing text if `undefined`. ## FAQ @@ -256,8 +267,8 @@ The new text of the spinner when the promise is rejected. If undefined, will kee Use [Chalk](https://github.com/chalk/chalk): ```js -const ora = require('ora'); -const chalk = require('chalk'); +import ora from 'ora'; +import chalk from 'chalk'; const spinner = ora(`Loading ${chalk.red('unicorns')}`).start(); ``` diff --git a/test.js b/test.js index 6307c5b..95fb2dc 100644 --- a/test.js +++ b/test.js @@ -1,10 +1,11 @@ -import {PassThrough as PassThroughStream} from 'stream'; +import process from 'node:process'; +import {PassThrough as PassThroughStream} from 'node:stream'; import getStream from 'get-stream'; import test from 'ava'; import stripAnsi from 'strip-ansi'; -import Ora from './index.js'; import TransformTTY from 'transform-tty'; import cliSpinners from 'cli-spinners'; +import ora, {oraPromise} from './index.js'; const spinnerCharacter = process.platform === 'win32' ? '-' : '⠋'; const noop = () => {}; @@ -21,13 +22,13 @@ const doSpinner = async (fn, extraOptions = {}) => { const stream = getPassThroughStream(); const output = getStream(stream); - const spinner = new Ora({ + const spinner = ora({ stream, text: 'foo', color: false, isEnabled: true, isSilent: false, - ...extraOptions + ...extraOptions, }); spinner.start(); @@ -48,7 +49,6 @@ test('main', macro, spinner => { test('title shortcut', async t => { const stream = getPassThroughStream(); const output = getStream(stream); - const ora = Ora; const spinner = ora('foo'); spinner.stream = stream; @@ -64,13 +64,13 @@ test('title shortcut', async t => { }); test('`.id` is not set when created', t => { - const spinner = new Ora('foo'); + const spinner = ora('foo'); t.falsy(spinner.id); t.false(spinner.isSpinning); }); test('ignore consecutive calls to `.start()`', t => { - const spinner = new Ora('foo'); + const spinner = ora('foo'); spinner.start(); const {id} = spinner; spinner.start(); @@ -78,10 +78,10 @@ test('ignore consecutive calls to `.start()`', t => { }); test('chain call to `.start()` with constructor', t => { - const spinner = new Ora({ + const spinner = ora({ stream: getPassThroughStream(), text: 'foo', - isEnabled: true + isEnabled: true, }).start(); t.truthy(spinner.id); @@ -146,16 +146,16 @@ test('.stopAndPersist() - isSilent:true can be disabled', macro, spinner => { spinner.stopAndPersist({symbol: '@', text: 'all done'}); }, /@ all done\n$/, {isSilent: true}); -test('.promise() - resolves', async t => { +test('oraPromise() - resolves', async t => { const stream = getPassThroughStream(); const output = getStream(stream); const resolves = Promise.resolve(1); - Ora.promise(resolves, { + oraPromise(resolves, { stream, text: 'foo', color: false, - isEnabled: true + isEnabled: true, }); await resolves; @@ -164,18 +164,18 @@ test('.promise() - resolves', async t => { t.regex(stripAnsi(await output), /[√✔] foo\n$/); }); -test('.promise() - rejects', async t => { +test('oraPromise() - rejects', async t => { const stream = getPassThroughStream(); const output = getStream(stream); const rejects = Promise.reject(new Error()); // eslint-disable-line unicorn/error-message try { - await Ora.promise(rejects, { + await oraPromise(rejects, { stream, text: 'foo', color: false, - isEnabled: true - }) + isEnabled: true, + }); } catch {} stream.end(); @@ -202,11 +202,11 @@ test('erases wrapped lines', t => { cursorAtRow = 0; }; - const spinner = new Ora({ + const spinner = ora({ stream, text: 'foo', color: false, - isEnabled: true + isEnabled: true, }); spinner.render(); @@ -265,10 +265,10 @@ test('reset frameIndex when setting new spinner', async t => { const stream = getPassThroughStream(); const output = getStream(stream); - const spinner = new Ora({ + const spinner = ora({ stream, isEnabled: true, - spinner: {frames: ['foo', 'fooo']} + spinner: {frames: ['foo', 'fooo']}, }); spinner.render(); @@ -284,10 +284,10 @@ test('reset frameIndex when setting new spinner', async t => { }); test('set the correct interval when changing spinner (object case)', t => { - const spinner = new Ora({ + const spinner = ora({ isEnabled: false, spinner: {frames: ['foo', 'bar']}, - interval: 300 + interval: 300, }); t.is(spinner.interval, 300); @@ -298,10 +298,10 @@ test('set the correct interval when changing spinner (object case)', t => { }); test('set the correct interval when changing spinner (string case)', t => { - const spinner = new Ora({ + const spinner = ora({ isEnabled: false, spinner: 'dots', - interval: 100 + interval: 100, }); t.is(spinner.interval, 100); @@ -314,18 +314,22 @@ test('set the correct interval when changing spinner (string case)', t => { if (process.platform !== 'win32') { test('throw when incorrect spinner', t => { - const ora = new Ora(); + const spinner = ora(); t.throws(() => { - ora.spinner = 'random-string-12345'; - }, /no built-in spinner/); + spinner.spinner = 'random-string-12345'; + }, { + message: /no built-in spinner/, + }); }); } test('throw when spinner is set to `default`', t => { t.throws(() => { - new Ora({spinner: 'default'}); // eslint-disable-line no-new - }, /no built-in spinner/); + ora({spinner: 'default'}); + }, { + message: /no built-in spinner/, + }); }); test('indent option', t => { @@ -336,12 +340,12 @@ test('indent option', t => { cursorAtRow = indent; }; - const spinner = new Ora({ + const spinner = ora({ stream, text: 'foo', color: false, isEnabled: true, - indent: 7 + indent: 7, }); spinner.render(); @@ -353,16 +357,18 @@ test('indent option', t => { test('indent option throws', t => { const stream = getPassThroughStream(); - const spinner = new Ora({ + const spinner = ora({ stream, text: 'foo', color: false, - isEnabled: true + isEnabled: true, }); t.throws(() => { spinner.indent = -1; - }, 'The `indent` option must be an integer from 0 and up'); + }, { + message: 'The `indent` option must be an integer from 0 and up', + }); }); test('handles wrapped lines when length of indent + text is greater than columns', t => { @@ -370,11 +376,11 @@ test('handles wrapped lines when length of indent + text is greater than columns stream.isTTY = true; stream.columns = 20; - const spinner = new Ora({ + const spinner = ora({ stream, text: 'foo', color: false, - isEnabled: true + isEnabled: true, }); spinner.render(); @@ -409,14 +415,16 @@ test('.stopAndPersist() with dynamic prefixText', macro, spinner => { // New clear method tests const currentClearMethod = transFormTTY => { - const spinner = new Ora({ + const spinner = ora({ text: 'foo', color: false, isEnabled: true, stream: transFormTTY, spinner: { - frames: ['-'] - } + frames: [ + '-', + ], + }, }); let firstIndent = true; @@ -426,8 +434,8 @@ const currentClearMethod = transFormTTY => { return this; } - for (let i = 0; i < this.linesToClear; i++) { - if (i > 0) { + for (let index = 0; index < this.linesToClear; index++) { + if (index > 0) { this.stream.moveCursor(0, -1); } @@ -435,9 +443,9 @@ const currentClearMethod = transFormTTY => { this.stream.cursorTo(this.indent); } - // It's too quick to be noticeable, but indent doesn't get applied - // for the first render if linesToClear = 0. New clear method - // doesn't have this issue, since it's called outside of the loop + // It's too quick to be noticeable, but indent does not get applied + // for the first render if `linesToClear === 0`. The new clear method + // doesn't have this issue, since it's called outside of the loop. if (this.linesToClear === 0 && firstIndent && this.indent) { this.stream.cursorTo(this.indent); firstIndent = false; @@ -455,9 +463,10 @@ test.serial('new clear method test, basic', t => { const transformTTY = new TransformTTY({crlf: true}); transformTTY.addSequencer(); transformTTY.addSequencer(null, true); + /* - If the frames from this sequence differ from the previous sequence, - it means the spinner.clear method has failed to fully clear output between calls to render + If the frames from this sequence differ from the previous sequence, + it means the `spinner.clear()` method has failed to fully clear output between calls to render. */ const currentClearTTY = new TransformTTY({crlf: true}); @@ -465,14 +474,16 @@ test.serial('new clear method test, basic', t => { const currentOra = currentClearMethod(currentClearTTY); - const spinner = new Ora({ + const spinner = ora({ text: 'foo', color: false, isEnabled: true, stream: transformTTY, spinner: { - frames: ['-'] - } + frames: [ + '-', + ], + }, }); currentOra.render(); @@ -532,18 +543,18 @@ test('new clear method test, erases wrapped lines', t => { return cursor.y === 0 ? 0 : cursor.y * -1; }; - const clearedLines = () => { - return transformTTY.toString().split('\n').length; - }; + const clearedLines = () => transformTTY.toString().split('\n').length; - const spinner = new Ora({ + const spinner = ora({ text: 'foo', color: false, isEnabled: true, stream: transformTTY, spinner: { - frames: ['-'] - } + frames: [ + '-', + ], + }, }); currentOra.render(); @@ -621,20 +632,20 @@ test('new clear method test, erases wrapped lines', t => { '- foo\n\nbar', '- 00000000000000000000000000000000000000\n000000000000', '- 00000000000000000000000000000000000000\n000000000000', - '- 🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + - '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + - '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄', - '- 🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + - '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + - '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄', - '- 🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + - '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + - 'foo', - '- 🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + - '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + - 'foo', + '- 🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + + '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + + '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄', + '- 🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + + '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + + '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄', + '- 🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + + '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + + 'foo', + '- 🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + + '🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄\n' + + 'foo', + 'foo\n - \nbar', 'foo\n - \nbar', - 'foo\n - \nbar' ]); t.deepEqual(frames, clearedFrames); @@ -665,9 +676,7 @@ test('new clear method, stress test', t => { return result; }; - const randos = () => { - return rAnDoMaNiMaLs(rando(5, 15), rando(25, 50)); - }; + const randos = () => rAnDoMaNiMaLs(rando(5, 15), rando(25, 50)); const randomize = (s1, s2) => { const spnr = cliSpinners.random; @@ -691,10 +700,10 @@ test('new clear method, stress test', t => { const currentOra = currentClearMethod(currentClearTTY); - const spinner = new Ora({ + const spinner = ora({ color: false, isEnabled: true, - stream: transformTTY + stream: transformTTY, }); randomize(spinner, currentOra);