npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@noravel/command

v1.0.5

Published

```bash npm install @noravel/command ```

Readme

Noravel Command

Installation

npm install @noravel/command

Content

Create handler

Create a handler file in your project.

touch noravel

Open a noravel file and add the following code:

#!/usr/bin/env node

import { Kernel } from '@noravel/command';

const kernel = new Kernel(process.argv);
kernel.run();

Create command

Create a command file in your project.

touch Commands/Greeting.js

Open a Commands/Greeting.js file and add the following code:

import { Command } from '@noravel/command';

class Greeting extends Command {
    signature = 'greeting';
    description = 'Sending greetings to someone';

    async handle() {
        console.log('Hello World');
    }
}

export default Greeting;

Make sure your command class exists the handle method. Then you can register your command in the noravel file.

#!/usr/bin/env node

import { Kernel } from '@noravel/command';
import Greeting from './Commands/Greeting.js';

const kernel = new Kernel(process.argv);
kernel.register([
    Greeting,
]).run();

Now, you can run your command like this:

./noravel greeting

Defining input expectations

When writing console commands, it is common to gather input from the user through arguments or options. Noravel Command makes it very convenient to define the input you expect from the user using the signature property on your commands. The signature property allows you to define the name, arguments, and options for the command in a single, expressive.

Arguments

All user supplied arguments and options are wrapped in curly braces. In the following example, the command defines one required argument: user:

signature = 'greeting {user}';

You may also make arguments optional or define default values for arguments:

// Optional argument
signature = 'greeting {user?}';

// Optional argument with default value
signature = 'greeting {user=Nam}';

Options

Options, like arguments, are another form of user input. Options are prefixed by two hyphens (--) when they are provided via the command line. There are two types of options: those that receive a value and those that don't. Options that don't receive a value serve as a boolean "switch". Let's take a look at an example of this type of option:

signature = 'greeting {--verbose}';

In this example, the --verbose switch may be specified when calling your command. If the --verbose switch is passed, the value of the option will be true. Otherwise, the value will be false:

./noravel greeting --verbose

Options with values

Next, let's take a look at an option that expects a value. If the user must specify a value for an option, you should suffix the option name with a = sign:

signature = 'greeting {--verbose=}';

In this example, the user may pass a value for the option like so. If the option is not specified when invoking the command, its value will be undefined:

./noravel greeting --verbose=Default

You may assign default values to options by specifying the default value after the option name. If no option value is passed by the user, the default value will be used:

signature = 'greeting {--verbose=Default}';

Option shortcuts

To assign a shortcut when defining an option, you may specify it before the option name and use the | character as a delimiter to separate the shortcut from the full option name:

signature = 'greeting {--v|verbose=}';

When invoking the command on your terminal, option shortcuts should be prefixed with a single hyphen and no = character should be included when specifying a value for the option:

./noravel greeting -vDefault

Input arrays

If you would like to define arguments or options to expect multiple input values, you may use the * character. First, let's take a look at an example that specifies such an argument:

signature = 'greeting {user*}';

When running this command, the user arguments may be passed in order to the command line. For example, the following command will set the value of user to an array with 1 and 2 as its values:

./noravel greeting user1 user2

This * character can be combined with an optional argument definition to allow zero or more instances of an argument:

signature = 'greeting {user?*}';

Option arrays

When defining an option that expects multiple input values, each option value passed to the command should be prefixed with the option name:

signature = 'greeting {--tag=*}';

Such a command may be invoked by passing multiple --tag arguments:

./noravel greeting --tag=tag1 --tag=tag2

Input descriptions

You may assign descriptions to input arguments and options by separating the argument name from the description using a colon. If you need a little extra room to define your command, feel free to spread the definition across multiple lines:

signature = `greeting {name : The name of the person to greet}
  {--v|verbose : Increase the verbosity of messages}
  {--tag=* : Tags to apply to the greeting}`;

Note: If your command contains required arguments, the user will receive a thrown error when they are not provided.

Command I/O

Retrieving Input

While your command is executing, you will likely need to access the values for the arguments and options accepted by your command. To do so, you may use the getArgument and getOption methods. If an argument or option does not exist, undefined will be returned:

async handle() {
  const name = this.getArgument('name');
  const verbose = this.getOption('verbose');
}

If you need to retrieve all of the arguments as an array, call the getArgument method without any parameters:

async handle() {
  const arguments = this.getArgument();
}

Options may be retrieved just as easily as arguments using the option method. To retrieve all of the options as an array, call the getOption method without any parameters:

async handle() {
  const options = this.getOption();
}

Prompting for input

In addition to displaying output, you may also ask the user to provide input during the execution of your command. The ask method will prompt the user with the given question, accept their input, and then return the user's input back to your command:

async handle() {
  const name = this.prompt.ask('What is your name?');
}

The secret method is similar to ask, but the user's input will not be visible to them as they type in the console. This method is useful when asking for sensitive information such as passwords:

async handle() {
  const password = this.prompt.secret('What is your password?');
}

Multiple choice questions

If you need to give the user a predefined set of choices when asking a question, you may use the choice method. You may set the array index of the default value to be returned if no option is chosen by passing the index as the third argument to the method:

async handle() {
  const choice = this.prompt.choice('What is your favorite color?', ['red', 'green', 'blue'], defaultIndex);
}

In addition, the choice method accepts optional fourth argument for determining whether multiple selections are permitted:

const choices = this.prompt.choice('What is your favorite color?', ['red', 'green', 'blue'], defaultIndex, true);

Writing Output

To send output to the console, you may use the line, info, comment, success, warning, and error methods. Each of these methods will use appropriate ANSI colors for their purpose. For example, let's display some general information to the user.

async handle() {
  this.output.info('This is an info message');
  this.output.success('This is a success message');
  this.output.warning('This is a warning message');
  this.output.error('This is an error message');
  this.output.comment('This is a comment message');
}

Table

The table method makes it easy to correctly format multiple rows / columns of data. All you need to do is provide the column names and the data for the table and Noravel Command will automatically calculate the appropriate width and height of the table for you:

async handle() {
  this.output.table(
    ['id', 'name', 'email', 'date of birth'],
    [
      [1, 'John Doe', '[email protected]', '2000-01-01'],
      [2, 'Jane Doe', '[email protected]', '1999-01-01'],
      [3, 'James Doe', '[email protected]', '2010-01-01'],
      [4, 'John Smith', '[email protected]', '2000-11-01'],
      [5, 'Jane Smith', '[email protected]', '2000-01-21'],
      [6, 'James Smith', '[email protected]', '2001-01-01'],
    ]
  );
}

Progress Bars

For long running tasks, it can be helpful to show a progress bar that informs users how complete the task is. First, define the total number of steps the process will iterate through. Then, advance the progress bar after processing each item.

async handle() {
  const bar = this.output.createProgressBar(100);
  bar.start();
  for (let i = 0; i < units; i++) {
    // Do some work...
    bar.advance();
  }
  bar.finish();
}

Progress Bar Methods

The progress bar provides several methods to control its behavior:

async handle() {
  const bar = this.output.createProgressBar(100);
  
  // Start the progress bar with an optional message
  bar.start('Processing items...');
  
  // Advance the progress by one step
  bar.advance();
  
  // Set a different total after creation
  bar.setTotal(150);
  
  // Get the current total
  const total = bar.getTotal();
  
  // Set the progress bar size (in characters)
  bar.setSize(50);
  
  // Get the current size
  const size = bar.getSize();
  
  // Finish the progress bar with an optional message
  bar.finish('Processing completed!');
}

Progress Bar Formats

The progress bar supports three different display formats:

async handle() {
  const bar = this.output.createProgressBar(100);
  
  // Normal format (default): [=====>     ] 50.0% 50/100
  bar.setFormat('normal');
  
  // Verbose format: [=====>] 50.0% 50/100 remaining: 25.0s. elapsed: 12.5s.
  bar.setFormat('verbose');
  
  // Minimal format: Progress: 50.0%
  bar.setFormat('minimal');
  
  bar.start();
  for (let i = 0; i < 100; i++) {
    bar.advance();
  }
  bar.finish();
}

Progress Bar Styles

You can choose between different progress bar styles:

async handle() {
  const bar = this.output.createProgressBar(100);
  
  // Arrow style (default): [=====>-----]
  bar.useArrowProgress();
  
  // Shape style: [#####_____]
  bar.useShapeProgress();
  
  // Block style: [█████░░░░░]
  bar.useBlockProgress();
  
  bar.start();
  for (let i = 0; i < 100; i++) {
    bar.advance();
  }
  bar.finish();
}

Constructor Options

When creating a progress bar, you can specify custom options:

async handle() {
  // Create progress bar with custom size (in characters)
  const bar = this.output.createProgressBar(100, 80);
  
  // Create progress bar that uses full terminal width
  const fullBar = this.output.createProgressBar(100, null);
  
  bar.start();
  for (let i = 0; i < 100; i++) {
    bar.advance();
  }
  bar.finish();
}

Create a maker command

Create a command file in your project.

touch Commands/ControllerMaker.js

Open a Commands/ControllerMaker.js file and add the following code:

import { MakerCommand } from '@noravel/command';

class ControllerMaker extends MakerCommand {
    signature = `make:controller
      {name : The name of the controller}
      {--m|model= : Generate a resource controller for the given model}
      {--f|force : Create the class even if the controller already exists}`;
    description = 'Create a new controller class';

    async handle() {
        console.log('Creating controller...');
    }
}

export default ControllerMaker;

Now let register the command in the noravel file:

#!/usr/bin/env node

import { Kernel } from '@noravel/command';
import Greeting from './Commands/Greeting.js';
import ControllerMaker from './Commands/ControllerMaker.js';

const kernel = new Kernel(process.argv);
kernel.register([
    Greeting,
    ControllerMaker,
]).run();

Let's look at the methods available in the MakerCommand class:

class MakerCommand {
    // Returns the base path of the project
    public basePath(dirPath?: string): string;

    // Returns the filename; if the user hasn't entered it, it will wait for user input
    public async fileName(question?: string = 'What should the file be named?'): Promise<string>;
    
    // Creates a file with the given name and path
    public makeFile(fileName: string, dirPath: string): void;
    
    // Returns the message that the file already exists
    protected fileAlreadyExists(filePath: string): string;
    
    // Returns the message that the file created successfully
    protected fileCreatedSuccessfully(filePath: string): string;
    
    // Returns the contents of a file that will be written to the file being created
    protected contentFile(fileName: string): string;
}

Help command

Check the available commands:

./noravel --help

Output:

Usage:
  command [arguments] [--options]

Available commands:
  greeting                Sending greetings to someone
  make:controller         Create a new controller class

Options:
  -h, --help             Show this help message
  -v, --version          Display the version of Noravel Command

You can also view a description of a specific command by:

./noravel make:controller --help

Output:

Description:
  Create a new controller class

Usage:
  make:controller [options] [--] <name>

Arguments:
  name                    The name of the controller

Options:
  -m, --model             Generate a resource controller for the given model
  -f, --force             Create the class even if the controller already exists
  -h, --help              Display help for the given command
  -v, --version           Display the version of Noravel Command

Programmatically executing commands

Sometimes you may wish to execute your command outside of the CLI. For example, you may wish to execute your command from a route or controller. You may use the call method on the Executor to accomplish this. The call method accepts either the command's class name as its first argument, and an array of command parameters as the second argument.

import Executor from './Executor.js';
import Greeting from './Commands/Greeting.js';

await Executor.call(Greeting, [
  'John Doe',
  '--verbose',
  '--tag=foo',
  '--tag=bar',
]);