Skip to content

Commit 9c01990

Browse files
authoredAug 23, 2021
Improve ora.promise() (#181)
1 parent d51c971 commit 9c01990

File tree

5 files changed

+92
-33
lines changed

5 files changed

+92
-33
lines changed
 

‎index.d.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,22 @@ declare namespace ora {
133133
readonly prefixText?: string | PrefixTextGenerator;
134134
}
135135

136+
interface PromiseOptions<T> extends Options {
137+
/**
138+
The new text of the spinner when the promise is resolved.
139+
140+
If undefined, will keep the initial text.
141+
*/
142+
successText?: string | ((result: T) => string);
143+
144+
/**
145+
The new text of the spinner when the promise is rejected.
146+
147+
If undefined, will keep the initial text.
148+
*/
149+
failText?: string | ((error: Error) => string);
150+
}
151+
136152
interface Ora {
137153
/**
138154
A boolean of whether the instance is currently spinning.
@@ -259,19 +275,19 @@ declare const ora: {
259275
}, 1000);
260276
```
261277
*/
262-
(options?: ora.Options | string): ora.Ora;
278+
(options?: string | ora.Options): ora.Ora;
263279

264280
/**
265-
Starts a spinner for a promise. The spinner is stopped with `.succeed()` if the promise fulfills or with `.fail()` if it rejects.
281+
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.
266282
267283
@param action - The promise to start the spinner for.
268284
@param options - If a string is provided, it is treated as a shortcut for `options.text`.
269285
@returns The spinner instance.
270286
*/
271-
promise(
272-
action: PromiseLike<unknown>,
273-
options?: ora.Options | string
274-
): ora.Ora;
287+
promise<T>(
288+
action: PromiseLike<T> | ((spinner: ora.Ora) => PromiseLike<T>),
289+
options?: string | ora.PromiseOptions<T>
290+
): Promise<T>;
275291
};
276292

277293
export = ora;

‎index.js

+27-15
Original file line numberDiff line numberDiff line change
@@ -393,23 +393,35 @@ const oraFactory = function (options) {
393393

394394
module.exports = oraFactory;
395395

396-
module.exports.promise = (action, options) => {
396+
// https://github.com/sindresorhus/ora/issues/169#issuecomment-873269524
397+
module.exports.promise = async (action, options) => {
398+
const actionIsFunction = typeof action === 'function';
397399
// eslint-disable-next-line promise/prefer-await-to-then
398-
if (typeof action.then !== 'function') {
399-
throw new TypeError('Parameter `action` must be a Promise');
400-
}
400+
const actionIsPromise = typeof action.then === 'function';
401401

402-
const spinner = new Ora(options);
403-
spinner.start();
402+
if (!actionIsFunction && !actionIsPromise) {
403+
throw new TypeError('Parameter `action` must be a Function or a Promise');
404+
}
404405

405-
(async () => {
406-
try {
407-
await action;
408-
spinner.succeed();
409-
} catch {
410-
spinner.fail();
411-
}
412-
})();
406+
const {successText, failText} = typeof options === 'object' ?
407+
options :
408+
{successText: undefined, failText: undefined};
413409

414-
return spinner;
410+
const spinner = new Ora(options); // Set the initial string or ora options.
411+
spinner.start();
412+
try {
413+
const promise = actionIsFunction ? action(spinner) : action;
414+
const result = await promise;
415+
spinner.succeed(successText === undefined ?
416+
undefined :
417+
(typeof successText === 'string' ? successText : successText(result))
418+
);
419+
return result;
420+
} catch (error) {
421+
spinner.fail(failText === undefined ?
422+
undefined :
423+
(typeof failText === 'string' ? failText : failText(error))
424+
);
425+
throw error;
426+
}
415427
};

‎index.test-d.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,27 @@ spinner.render();
4545
spinner.frame();
4646

4747
const resolves = Promise.resolve(1);
48-
promise(resolves, 'foo');
49-
promise(resolves, {
48+
void promise(resolves, 'foo');
49+
void promise(resolves, {
5050
stream: new PassThroughStream(),
5151
text: 'foo',
5252
color: 'blue',
5353
isEnabled: true,
5454
isSilent: false
5555
});
56+
void promise(async () => {
57+
await resolves;
58+
}, 'foo');
59+
void promise(async spinner => {
60+
spinner.prefixText = 'foo';
61+
await resolves;
62+
return 7;
63+
}, {
64+
stream: new PassThroughStream(),
65+
text: 'foo',
66+
color: 'blue',
67+
isEnabled: true,
68+
isSilent: false,
69+
successText: result => `Resolved with number ${result}`,
70+
failText: 'bar'
71+
});

‎readme.md

+19-2
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,28 @@ Change the spinner indent.
226226
### ora.promise(action, text)
227227
### ora.promise(action, options)
228228

229-
Starts a spinner for a promise. The spinner is stopped with `.succeed()` if the promise fulfills or with `.fail()` if it rejects. Returns the spinner instance.
229+
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.
230230

231231
#### action
232232

233-
Type: `Promise`
233+
Type: `Promise | ((spinner: ora.Ora) => Promise)`
234+
235+
#### options
236+
237+
Type: `object`
238+
239+
All of the [options](#options) plus the following:
240+
241+
##### successText
242+
Type: `string | ((result: T) => string)`
243+
244+
The new text of the spinner when the promise is resolved. If undefined, will keep the initial text.
245+
246+
##### failText
247+
Type: `string | ((error: Error) => string)`
248+
249+
The new text of the spinner when the promise is rejected. If undefined, will keep the initial text.
250+
234251

235252
## FAQ
236253

‎test.js

+6-8
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,13 @@ test('.promise() - rejects', async t => {
169169
const output = getStream(stream);
170170
const rejects = Promise.reject(new Error()); // eslint-disable-line unicorn/error-message
171171

172-
Ora.promise(rejects, {
173-
stream,
174-
text: 'foo',
175-
color: false,
176-
isEnabled: true
177-
});
178-
179172
try {
180-
await rejects;
173+
await Ora.promise(rejects, {
174+
stream,
175+
text: 'foo',
176+
color: false,
177+
isEnabled: true
178+
})
181179
} catch {}
182180

183181
stream.end();

0 commit comments

Comments
 (0)
Please sign in to comment.