Skip to content

Collect input from a user. CLI, Interactive Prompts, and JS interfaces.

License

Notifications You must be signed in to change notification settings

wesleytodd/opta

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

opta

We all have choices to make

NPM Version NPM Downloads test js-standard-style

Collect user input from cli flags, interactive prompts, and JS input.

Usage

$ npm i opta
const opta = require('opta')

// Create an opta instance
const opts = opta({
  options: {
    time: {
      type: 'number'
    },
    hello: {
      default: 'hello'
    },
    world: {
      default: 'world'
    }
  }
})

// .cli() returns an instance of yargs,
// configured with the options
const yargsInstance = opts.cli()

// Will set the appropriate values as
// configured on the yargs instance
yargsInstance(process.argv.slice(2))

// Set some overrides. These will take precedence,
// but also will prevent `.prompt()` from asking
// the user
opts.overrides(overrides)

// Set detauls. These will be used as
// defaults when prompting, and fill in
// values not specified in other ways
opts.defaults(defaults)

// Display prompts using inquirer, will
// populate values with input from user
const promptor = opts.prompt()
await promptor()

// Get the values after cli, overrides,
// and prompt input
const values = opts.values()

// An example of using the values
setTimeout(() => {
  console.log(`${values.hello} ${values.world}`)
}, values.time)

Composition of options

One of the primary focuses of opta is to enable easy composition of inputs across projects. If a project exports it's opta instance, another can simply combine their options parameters like this:

const opta = require('opta')

// Project One exports a key `opts` which is
// an instance of `opta`, along with it's other functionality
const projectOne = require('project-one')

// My Project which wants to expose functionality from
// Project One can simply merge `opts.options` into the
// options passed to my instance
const myOpts = opta({
  options: {
    ...projectOne.opts.options,
    myOptions: true,
    // You can also simply override the options descriptor
    // from `projectOne.opts`.  In this example we disable
    // the prompt but leave the rest alone
    projectOneOpt: {
      ...projectOne.opts.options.projectOneOpt,
      prompt: false
    }
  }
})

// Now when we call .cli(), .prompt(), and .values()
// we will get options from both the composed options
// and our projects
await myOpts.prompt()
const vals = myOpts.values()
console.log(vals) // all options from both Project and My Project

Prompt Testing

Testing user input can be difficult. This package exports a test helper which can mimic different behaviors of users interacting with prompts without dealing with the complicated work to actually handle user input. Here is an example:

const test = require('node:test');
const assert = require('node:assert')
const opta = require('opta')
const optaUtils = require('opta/utils')

test('some test', async (t) => {
  const opts = opta({
    options: {
      foo: true,
      bar: true
    },
    // Create a promptModule mock
    promptModule: optaUtils.test.promptModule({
      // Will assert that two prompts were displayed
      assertCount: 2,
      prompts: {
        foo: {
          // Set a value as if it was user input
          value: 'foo',
          
          // Assert some things about the prompt config
          // which is passed on to inquirer
          assert: (p) =>{
            assert.strictEqual(p.name, 'foo')
            assert.strictEqual(p.message, 'foo:')
            assert.strictEqual(p.type, 'input')
            assert.strictEqual(p.when, true)
          },

          // Setup a context object which is passed to the prompt
          // default if it is a function
          defaultContext: {}
        },

        // Or more simply, just set value directly
        bar: 'bar'
      }
    })
  })

  // Run the opta prompts
  await opts.prompt()()
  const values = opts.values({ baz: 'baz' })
  assert.deepStrictEqual(values, {
    foo: 'foo',
    bar: 'bar',
    baz: 'baz'
  })
})

About

Collect input from a user. CLI, Interactive Prompts, and JS interfaces.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published