@poppinss/cliui
    TypeScript icon, indicating that this package has built-in type declarations

    2.2.5 • Public • Published

    CLI UI

    Command line UI Kit used by AdonisJS

    This repo is a command line UI Kit used by the AdonisJS framework to design its command line interfaces.

    The kit is highly opinionated and we will not allow configurable settings in the near future. We want to be consistent with our UI's without worrying about the configuration.

    gh-workflow-image typescript-image npm-image license-image synk-image

    Table of contents

    Installation

    Install the package from the npm registry by running following command.

    npm i @poppinss/cliui
    
    # Yarn users
    yarn add @poppinss/cliui

    Usage

    Import the components you want to use from the package.

    import { logger, instructions, sticker, tasks, table } from '@poppinss/cliui'
    logger.info('hello world')
    
    const spinner = logger.await('downloading')
    
    await someTimeConsumingTask()
    spinner.stop()

    Logger

    The logger exposes the following methods.

    success(message, prefix?, suffix?)

    Log success message. The message is printed to stdout.

    logger.success('Account created')
    
    // [ success ]  Account created

    Optional prefix

    logger.success('Account created', 'ap-south-1')
    
    // [ap-south-1] [ success ]  Account created

    Optional suffix

    logger.success('Account created', undefined, 'ap-south-1')
    
    // [ success ]  Account created (ap-south-1)

    The prefix and suffix are support on all logger methods except logger.action

    error(message, prefix?, suffix?)

    Log an error message. The message is printed to stderr.

    logger.error('Unable to write. Disk full')
    
    // Or log error object
    logger.error(new Error('Unable to write. Disk full'))
    
    // [ error ]  Unable to write. Disk full

    fatal(message, prefix?, suffix?)

    The logger.error does not print the error stack. You must use logger.fatal to print the error stack.

    logger.fatal(new Error('Unable to write. Disk full'))

    warning(message, prefix?, suffix?)

    Print a warning message. Message is written to stdout.

    logger.warning('Running out of disk space')
    
    // [ warn ]  Running out of disk space

    info(message, prefix?, suffix?)

    Print an info message. Message is again written to stdout.

    logger.info('Your account is has been updated')
    
    // [ info ]  Your account is has been updated

    debug(message, prefix?, suffix?)

    Print a debug message. Message is printed to stdout.

    logger.debug('Something just happened')
    
    // [ debug ]  Something just happened

    log(message)

    Similar to console.log, but instead uses the Logger renderer.

    We will talk about renderers later in this document, since they make testing of log message little bit easier.

    logger.log('hello world')

    logError(message)

    Similar to console.error, but instead use the Logger renderer.

    log.logError('this is an error message')

    logUpdate(message)

    Log a message that overwrites the previously logged message. The method is helpful for building progress bars or animations.

    logger.logUpdate(`downloading ${i}%`)
    
    // Once completed, persist the message on console
    logger.logUpdatePersist()

    Here is a complete example of showing the downloading progress.

    const sleep = () => new Promise((resolve) => setTimeout(resolve, 50))
    
    async function run() {
      for (let i = 0; i <= 100; i = i + 2) {
        await sleep()
        logger.logUpdate(`downloading ${i}%`)
      }
    
      logger.logUpdatePersist()
    }
    
    run()

    Action

    In order to log results of an action/task, we make use of the action method.

    const action = logger.action('create')
    action.succeeded('config/auth.ts')

    An action can end in one of the following states.

    action.succeeded(message)

    Action completed successfully

    const action = logger.action('create')
    action.succeeded('config/auth.ts')

    action.‌skipped(message)

    Skipped action

    const action = logger.action('create')
    action.skipped('app/Models/User.ts')

    action.failed(message, errorMessage)

    Action failed, an error message is required to share more context

    const action = logger.action('create')
    action.failed('server.ts', 'File already exists')

    Instructions

    Instructions are mainly the steps we want someone to perform in order to achieve something. For example:

    • Display instructions to start the development
    • Or display instructions to bundle the code for production
    import { instructions, logger } from '@poppinss/cliui'
    
    instructions()
      .add(`cd ${logger.colors.cyan('hello-world')}`)
      .add(`Run ${logger.colors.cyan('node ace serve --watch')} to start the server`)
      .render()
    • Calling the instructions() begins a new instructions block
    • Next, you can add new lines by using the .add() method.
    • Finally, call the render() method to render it on the console.

    Sticker

    Similar to the instructions, but a sticker does not prefix the lines with a pointer > arrow. Rest is all same.

    It is helpful for displaying a message that needs the most attention. For example:

    • Update the CLI version
    • Or, the address to access the local server
    import { sticker, logger } from '@poppinss/cliui'
    
    sticker()
      .add('Started HTTP server')
      .add('')
      .add(`Local address:    ${logger.colors.cyan('http://localhost:3333')}`)
      .add(`Network address:  ${logger.colors.cyan('http://localhost:3333')}`)
      .render()

    Tasks

    We make use of tasks when performing multiple actions in respond to a command. For example:

    • Create a new AdonisJS app
    • Or, Setup packages after installation

    The UI for the tasks is designed to only handle tasks running in sequence.

    Task Renderers

    Task has two renderers minimal and verbose. The minimal renderer is the default choice and switch to verbose in one of the following situations.

    • Command line is not interactive (no tty)
    • Or someone has explicitly opted for verbose output.

    Running tasks

    Following is a very simple example of creating and running multiple tasks.

    import { tasks } from '@poppinss/cliui'
    
    await tasks()
      .add('clone repo', async (logger, task) => {
        logger.info(`cloning ${someRepoUrl}`)
    
        await performClone()
        await task.complete()
      })
      .add('install dependencies', async (logger, task) => {
        const spinner = logger.await('running npm install')
    
        await performInstall()
        spinner.stop()
    
        await task.complete()
      })
      .run()
    • The add method accepts the task title and the callback function to invoke in order to perform the task
    • Once, you are done with the task jobs, you must call await task.complete() to complete the task. The await is important here.
    • In order to mark task as failed, you can call the task.fail method. All upcoming tasks will be stopped in case of a failure. ts await task.fail(new Error('Network error'))

    By default, the minimal renderer is used and pivots to the verbose renderer only when terminal is not interactive.

    Verbose renderer

    In order to run tasks explicitly in the verbose mode, you can create the tasks instance using tasks.verbose() method.

    tasks.verbose().add().add().run()

    Install

    npm i @poppinss/cliui

    DownloadsWeekly Downloads

    11,175

    Version

    2.2.5

    License

    MIT

    Unpacked Size

    80 kB

    Total Files

    35

    Last publish

    Collaborators

    • virk