@magic/cli
@magic/cli
declarative cli sanitization and execution for @magic
sanitizes cli flags from aliases to default names rewrites process.argv accordingly provides autogenerated --help output (that can be customized) also handles commands and environment for you
exports a commonjs file that allows to launch mjs files as clis
install
be in a nodejs project
npm i --save-dev @magic/cli
caveats
there are some quirks that need some careful consideration when designing a cli api.
depending on your requirements, these caveats may or may not apply.
last argument
if your last argument does not have a corresponding flag, it will still be assigned to the last flag prior to it.
workaround
do not design a cli with a trailing command.
option argument and command name clash
if one of your options gets an argument that is equal to a command, this command will be executed.
workaround
do not name your commands like the possible arguments.
flag arguments can not start with a dash
cli arguments that start with a - will always be treated as flags, not values.
workaround
do not design a cli that accepts arguments that start with a -
those issues might get addressed in the future.
Usage
full api example
#!/usr/bin/env node
import cli from '@magic/cli/src/index.mjs''
const { argv, env, commands } = cli({
commands: [
['cmd1', 'cmd1alias'],
'cmd2',
],
options: [
['--flag1', '-f1'],
['--flag2', '-f2'],
],
default: {
'--default-key': 'default-value',
},
single: [
'--default-key',
],
required: [
'--default-key',
],
pure: true, // do neither change process.argv nor process.env
pureArgv: true, // do not change process.argv
pureEnv: true, // do not change process.env
})
options / argv
argv mappings will handle options and option aliases
using the cli file above
then, in your terminal / bash
bin.mjs -f1 arg1 arg2 -f2
resulting process.argv
process.argv = [
'/path/to/bin/node',
'/path/to/bin.mjs',
'--flag1'
'arg1',
'arg2',
'--flag2',
]
returned javascript object
argv === { '--flag1': ['arg1', arg2], '--flag2': []}
commands
cli commands can be handled too.
import cli from '@magic/cli/src/index.mjs'
const args = {
commands: [
['dev', 'development', 'start'],
'serve',
],
}
const argv = cli(args)
// call
./bin.mjs dev serve
// results:
{
cmds: ['dev', 'serve'],
commands: ['dev', 'serve'],
}
help output
@magic/cli will derive a help text from your configuration.
help itself can be configured to provide better error messages.
simple help message
import cli from '@magic/cli/src/index.mjs'
const args = {
commands: [['magic', 'm']],
options: [['--spell', '-s']],
prepend: 'prepend',
append: 'append',
help: 'custom help text',
}
const argv = cli(args)
// running
./bin.mjs
// without arguments
// help output
@magic/cli wrapped cli.
custom help text
cli commands
magic - aliases: ["m"]
possible command line flags:
--spell - aliases: ["-s"]
environment switches:
dev: set NODE_ENV to development - aliases ["development"]
detailed help message
the help property will accept an object which maps to the args object.
import cli from '@magic/cli/src/index.mjs'
const args = {
commands: [['magic', 'm']],
options: [['--spell', '-s']],
prepend: 'prepend',
append: 'append',
help: {
name: 'cli name',
text: 'custom help text',
commands: {
magic: 'magic info help text',
},
options: {
'--spell': 'cast a simple spell',
},
env: ['dev', 'set environment to development'],
},
}
const argv = cli(args)
// running
./bin.mjs
// without arguments
// help output
cli name
custom help text
commands:
magic - aliases: ["m"]
flags:
--spell - aliases: ["-s"]
environment switches:
dev: set process.NODE_ENV to development - aliases ["development"]
clean
some cli arguments will be expected to return a string instead of a list of arguments.
this can be achieved using the single array
const args = {
options: [['--single', '-s']],
single: ['--single'],
}
const res = cli(args)
console.log(res)
required
some cli arguments will be required.
this can be achieved using the required array.
if a required field is missing, a error message and the help will be shown.
const args = {
options: [['--required', '-r']],
required: ['--required'],
}
const res = cli(args)
console.log(res)
config
there are some configuration parameters that can be passed to the cli function
pure
const args = {
pure: false, // set to true to prevent changes to process.argv and process.env
pureEnv: false, // set to true to prevent changes to process.env
pureArgv: false, // set to true to prevent changes to process.argv
}
cli(args)
prepend/append
process.argv values can be prepended and appended
import cli from '@magic/cli/src/index.mjs'
const args = {
prepend: ['prepended']
append: ['appended']
}
cli(args)
default
use this to set default process.argv key: value pairs that should be set if they are not
import cli from '@magic/cli/src/index.mjs'
const args = {
options: [
['--default-key'],
],
default: {
'--default-key': 'default-value',
},
}
const argv = cli(args)
// returns
{
argv: {
'--default-key': 'default-value',
},
}
helpers
@magic/cli exports multiple promisified child_process commands.
exec
import cli from '@magic/cli'
const execOptions = {
// any child_process.exec options
}
const {
err,
stderr,
stdout
} = await cli.exec('cmd --flag Flag', execOptions)
execFile
const execFileOptions = {
// any child_process.execFile options
}
const {
err,
stderr,
stdout,
} = await cli.execFile('/path/to/file.x', ['--flag', 'Flag'], execFileOptions)
spawn
const spawnOptions = {
// any child_process.spawn options
}
const spawnedProcess = cli.spawn('program', ['--flag', 'Flag'], spawnOptions)
source
the source for this page is in the docsrc directory and gets built and published to github using @magic/core