opta
v1.1.0
Published
Collect user input from cli flags, interactive prompts, and js input.
Downloads
343
Maintainers
Readme
opta
We all have choices to make
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'
})
})