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 🙏

© 2024 – Pkg Stats / Ryan Hefner

cmdsettings

v1.0.5

Published

Allows for saving and loading options of Commander to and from setting files

Downloads

25

Readme

npm pipeline status coverage

cmdsettings

Allows for saving and loading options of Commander to and from setting files

General Usage

This package is an extension for the Commander framework to allow for saving and loading of options to and from files. Instead of defining options directly, like

program
    .option('-v, --verbose', 'Printout more', false)
    .option('--opt1 <string>', 'help1', 'def1')
    .option('--opt2 <file>', 'help2', 'def2');

you can define settings and use them to populate your commands with options, e.g.

const settings = {
    verbose: new Setting({ short: "v", name: "verbose", help: "Printout more", def: false, settings: false }),
    opt1: new Setting({ name: "opt1", help: "help1", def: "def1", }),
    opt2: new Setting({ name: "opt2", type: "file", help: "help2", def: "def2", }),
};

program
    .addOption(settings.verbose.toOption())
    .addOption(settings.opt1.toOption())
    .addOption(settings.opt2.toOption());

This looks like more work by first glance. But you get some benefits.

You can load the settings from a settings file (actually, multiple files), just by calling

await Setting.readSettings(settings, { settingsFolderName: ".mytool" });

This would try to load the file "settings.json" (the default name, maybe changed) in a directory ".mytool" in the current working directory. This would also try to load settings files in parent directories and the home directory of the user (if not already found in one of the parent directories).

So, if you have some options which are similar for a given project or the current user, just defined these options by means of settings in one of these files.

Important: The trick is, that setting values read from a setting file are used as default values for options. This way, the default commander.js behavior is not changed and you can simply use options without caring about the setting file. However, you need to read the settings before setting up the commands! As you may want to use verbosity settings when reading the settings files, you may want to use this pattern:

// manually check args for verbosity information, e.g.
const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
// and setup output functions, e.g.
const verb = (s) => {if (verbose) console.log(s)}
// ...

// read settings before setting up commands
await Setting.readSettings(SETTINGS, { 
       settingsFolderName: ".mytool", settingsFileName: "settings.json",
       log: log, verb: verb, error: error, debug: debug
    });

// setup program, e.g.
program.command('mycommand')
        .addOption(SETTINGS.someOption.toOption())  // value read from setting file will be used as default   
        .action(cmdMyCommand);

// and execute
program.parse();

In the command, you can then simply use the option, e.g.

function cmdMyCommand(options) {
    const someOption = options.someOption;
}

How do these setting files look like. Well, you can easily provide a command (or option, or however you want to do it) which generates a setting file based on the current values:

program.command("generateSettings").action(async () => {
    await Setting.writeSettings(settings, { settingsFolderName: ".mytool" });
});

The generated file is a json file with comments. All values matching the default value are added with line comments. Values which are diffent from the default value are directly set in the settings file. This makes it very easy for users to change the files. This is how the file for the example may look like:

{   /* Settings maybe overwritten by subfolder setting files or command line,
       overwrites values in parent settings files. */
    "opt1": "actVal1",         /* help1 (string, default: "def1") */
    // "opt2": "def2",            /* help2 (file, default: "def2") */
}

The settings have several mandatory properties:

  • name: Name of the setting, used as long option in command line
  • help: Help text for the setting
  • def: The default value of the setting

Most properties are optional:

  • short: Short option in command line
  • type: Type of the setting, used to generate help text; if not given, the type of the default value is used to infer the type.
  • embedded: boolean; Actual value may be embedded in settings file, e.g. as object or array. This can only be defined for file settings. Instead of the filename, the actual value is written to the settings file.
  • settings: boolean; If set to false, the setting is not loaded (or written) from a settings file. This is useful for settings that are only used as command line arguments but using the same mechanism as settings.

If the default value is an array, the settings is assumed to be variadic.

Of course, you can also combine the settings with plain commander options, command etc.

Logging

Since CLI tools often use differnt log levels, you can pass special log functions to read- and writeSettings. These functions mimic the signature of console.log etc., which are also the defaults:

  • log -> console.log
  • verb -> console.verb
  • warn -> console.warn
  • error -> console.err
  • debug -> console.debug

readSettings print out debug messages about which folders are examined and verbose messages where setting files are found.

You may want to manually parse args in order to make verbosity configurable in readSettings as well, see above for example.