@supercharge/console-io
v2.0.0
Published
Opinionated UI kit for CLI inputs and outputs
Downloads
37
Readme
Introduction
The @supercharge/console-io
package is a CLI UI kit. It provides an opinionated styling for console outputs and allows you to easily retrieve user retrieve input from the terminal.
Installation
npm i @supercharge/console-io
Table of Contents
Usage
Using @supercharge/console-io
is pretty straightforward.
const { ConsoleInput, ConsoleOutput } = require('@supercharge/console-io')
async function askForAndPrintTheName () {
const input = new ConsoleInput()
const output = new ConsoleOutput()
// asking the for input
const name = await io.ask('What’s your name')
// printing output to the terminal
output.success('Hello', name)
}
Input
The package exports a ConsoleInput
class. This class allows you to prompt users for input on the command line.
For example, you may ask the user for text input or to confirm/decline a given question.
Here’s how you create a console input instance called input
. The following console input examples refer to this input
instance when calling the individual methods.
const { ConsoleInput } = require('@supercharge/console-io')
const input = new ConsoleInput()
input.ask(message, builder?)
Prompts the user for text input:
const name = await input.ask('What’s your name')
The ask
method accepts an optional builder callback as the second argument. This builder callback allows you to refine the question. Refining the question can be defining a default value or transforming the answer:
const name = await input.ask('What’s your name', builder => {
builder
.defaultValue('Marcus')
.transform(answer => String(answer).toUpperCase())
})
// `name` when pressing enter using the default value: MARCUS
// `name` when providing 'test' as the value: TEST
input.confirm(message, builder?)
Prompts the user for a confirmation returning true
or false
:
const proceed = await input.confirm('This deletes all files. Proceed?')
The confirm
method accepts a builder callback as the second argument. This builder callback allows you to refine the question. Refining the question can be defining a default value or transforming the answer:
const proceed = await input.confirm('This deletes all files. Proceed?', builder => {
builder
.defaultValue(false)
.transform(answer => answer ? 1 : 0) // transforms `true` to `1` and `false` to `0`
})
// `proceed` when pressing enter using the default value: 0
// `proceed` when selecting the truthy value: 1
input.password(message, builder?)
Prompts the user for a password input. The typed input is masked with stars:
const password = await input.password('Provide your password')
The password
method accepts a builder callback as the second argument. This builder callback allows you to refine the password prompt: you can make the input visible, like the password prompts on Linux systems:
const password = await input.password('Provide your password (not visible when typing)', builder => {
builder
.invisible()
.transform(name => String(name).toLowerCase())
})
// `password` when typing "Supercharge": "supercharge"
input.secure(message)
Prompts the user for a secure input which is not visible when the user types the input:
const secret = await input.secure('Provide your password')
The secure
method accepts is a shortcut to an invisible password prompts. It doesn’t show the input, not even masked with stars.
input.choice(message, builder)
Prompts the user to select from a list of choices. Use the builder
in the callback function to create and configure the available choices:
const choice = await input.choice('Choose your favorite framework', builder => {
builder.add('Supercharge').withValue('supercharge')
builder.add('Express').withValue('express').disabled()
})
// `choice` when selecting "Supercharge": "supercharge"
Output
The package exports a ConsoleOutput
class. This class allows you to print expressive and colored messages to the terminal.
For example, you may use console output to create expressive and colored terminal messages.
Here’s how you create a console output instance called output
. The following console output examples refer to this output
instance when calling the individual methods:
const { ConsoleOutput } = require('@supercharge/console-io')
const output = new ConsoleOutput()
Logging
The console output exposes a handful methods. Here’s a preview how the console output looks like:
output.log(message)
Prints a log message to stdout
. Works like console.log
but uses the log renderer. Log renderers can be swapped for better testing:
output.log('Supercharge is sweet!')
output.logError(message)
Prints a log message to stderr
. Works like console.error
but uses the log renderer. Log renderers can be swapped for better testing:
output.log('Supercharge is sweet!')
output.blankLine()
Prints an empty line to the terminal. Useful to create whitespace:
output.blankLine()
output.info(message)
Prints the given info message
to the terminal. Info messages will be prefixed with an “INFO” tag on a cyan background:
output.info('info message')
output.warn(message)
Prints the given warning message
to the terminal. Warning messages will be prefixed with a “WARN” tag on a yellow background:
output.info('warning message')
output.debug(message)
Prints the given debug message
to the terminal. Debug messages will be prefixed with a “DEBUG” tag on a blue background:
output.debug('debug message')
output.error(message | Error)
Prints the given error message
or message from the Error
instance to the terminal. Error messages will be prefixed with an “ERROR” tag on a red background:
output.debug('debug message')
When providing an Error
instance, the stack trace will be printed dimmed below the error message.
output.success(labelOrMessage, message?)
Prints a success message to the terminal. When providing a single parameter to .success(message)
, the text will be printed in green. You may provide the label and message parameters to create a success tag for the given label
with the related message
:
// just a success message
output.success('Green-colored success message')
// success message with label
output.success('SUCCESS', 'success message')
output.hint(labelOrMessage, message?)
Prints a hint message to the terminal. When providing a single parameter to .hint(message)
, the text will be printed in blue. You may provide the label and message parameters to create a hint tag for the given label
with the related message
:
// just a hint message
output.hint('Blue-colored hint message')
// hint message with label
output.hint('SKIPPED', 'hint message')
output.fail(labelOrMessage, message?)
Prints a fail message to the terminal. When providing a single parameter to .fail(message)
, the text will be printed in red. You may provide the label and message parameters to create a fail tag for the given label
with the related message
:
// just a fail message
output.fail('Red-colored fail message')
// fail message with label
output.fail('FAILED', 'fail message')
Tags
The ConsoleOutput
class provides a .tag(label)
method creating a pending tag output. The pending tag must be completed with a given message. The tag message relates to one of the available states. The tag states define the colors. At this point, there are three tags availabe: success
, info
, failed
.
output.tag(label).success(message)
Prints a success tag to the terminal. The tag label
is printed with dark text on a green background. The message
provides more context data:
output.tag(' FINISHED ').success('Database migrations')
output.tag(label).info(message, reason?)
Prints an info tag to the terminal. The tag label
is printed with dark text on a blue background. The message
provides more context data:
output.tag(' IGNORED ').info('config/app.js file for this run')
output.tag(' SKIPPED ').info('Copying .env', 'File already exists.')
output.tag(label).failed(message, reason?)
Prints a fail tag to the terminal. The tag label
is printed with dark text on a red background. The message
provides more context data:
output.tag(' FAILED ').failed('to copy .env file', 'File already exists.')
Spinner
A ConsoleOutput
instance provides the .spinner(message)
and .withSpinner(message, callback)
methods creating and returning a loading spinner with the given message
. You can process long-running tasks while showing the loading spinner. You must manually stop the when using the .spinner(message)
method. Stopping and starting the spinner is handled for you when using the .withSpinner(message, callback)
method.
Spinner Interface
You can change the state (message) of a loading spinner by using one of the following three methods:
spinner.update(message)
: update the previous spinner text to the givenmessage
spinner.done(message?)
: stop the spinner and mark it as “done”. Optionally update the spinner text to the givenmessage
spinner.fail(message?)
: stop the spinner and mark it as “failed”. Optionally update the spinner text to the givenmessage
output.spinner(message)
Creates and returns a started loading spinner for the given message
:
const spinner = output.spinner('Installing dependencies')
await installDependencies()
spinner.update('Processing long-running task')
await processOtherLongRunningTask()
spinner.stop('Setup complete')
output.withSpinner(message, callback)
Returns a promise and runs the given callback
action. The callback
receives a started loading spinner instance. Using this method allows you to group actions of a long-running task into a callback function:
const result = await output.withSpinner('Installing dependencies', async spinner => {
await installDependencies()
spinner.update('Completing setup')
await completeSetup()
/**
* You can manually stop the spinner with a custom message. You can also skip
* stopping the spinner here if you’re fine using the previous message as
* the "done" message. Stopping the spinner is already handled for you.
*/
spinner.stop('Setup complete')
/**
* You may return a value from this callback and use it later in your code.
*/
return { done: true }
})
You must handle errors youself in case one of your methods inside the callback
throws an error. A common approach is wrapping your code in a try/catch
block and handling the error after catching it. Here’s an example on how you may handle errors:
try {
await output.withSpinner('A failing spinner', async () => {
throw new Error('Uff, failed!')
})
} catch (error) {
output.error(error.message)
}
Contributing
Do you miss a function? We very much appreciate your contribution! Please send in a pull request 😊
- Create a fork
- Create your feature branch:
git checkout -b my-feature
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request 🚀
License
MIT © Supercharge
superchargejs.com · GitHub @supercharge · Twitter @superchargejs