Commands
Configurator supports command-oriented applications using the Schema selector feature, which provides
hierarchical command structures through schema options.
- A property is marked as a
selectorto indicate it selects between alternatives. - Properties marked with
selectionare only evaluated when the selector matches a provided value (or the property name, if omitted). - You can define sub-commands within selection properties to build a command hierarchy.
- The command line parser recognizes these patterns and produces appropriate parsing behavior.
For example, here's an app defining a command schema:
import { Configurator, Schema } from '@versionzero/configurator';
const schema = new Schema('object')
.property('action', new Schema('string').selector())
.property('install', new Schema('object').selection()
.meta('description', 'install specified packages')
.property('packages', new Schema('array').meta('general')
.property('*', new Schema('string').meta('valueDescription', 'package-name'))
.required()
)
.property('save', new Schema('boolean'))
.property('save-dev', new Schema('boolean'))
.property('global', new Schema('boolean'))
)
.property('test', new Schema('object').selection()
.property('ignore-scripts', new Schema('boolean'))
)
.property('run', new Schema('object').selection()
.property('workspace', new Schema('string'))
.property('if-present', new Schema('boolean'))
.property('script', new Schema('string').required()
.meta('general')
.meta('valueDescription', 'script-name')
.meta('description', 'run script')
)
);
const context = {
appName: 'spm',
//argv: ['install', '-s', 'foo', 'bar']
//argv: ['--help']
}
const config = await new Configurator({schema}).configure(context);
console.log(config);
Running this with node spm.js --help produces:
Usage: spm [options] [install|run|test [options]]
--config (-C) [path|-] - load configuration from file (or -
for stdin)
--help (-h) [advanced] - display help information
install [options] <package-name...> - install specified packages
--global (-g) [true|false]
--save (-s) [true|false]
--save-dev (-S) [true|false]
test [options]
--ignore-scripts (-i) [true|false]
run [options] script-name
--if-present (-i) [true|false]
--workspace (-w) [string]
Running with node spm.js install -s foo bar yields
{
"action": "install",
"install": {
"packages": [ "foo", "bar" ],
"save": true
}
}
The selector pattern provides several benefits:
- The command line parser automatically recognizes the structure and parses hierarchically
- Environment variables work consistently:
SPM_INSTALL_SAVE,SPM_TEST_IGNORE_SCRIPTS, etc. - Only the selected command's properties are evaluated (properties for other commands are suppressed)
- The pattern naturally supports nested sub-commands
In other words, Configurator commands don't actually "do" anything on their own; they simply provide
structured hints for the command line to hierarchically assemble the configuration in a
friendly manner. The actual work of interpreting what a command "means" is up to the application.
See the API documentation for Schema
for more information on using the selector pattern.
(For a higher-level abstraction that builds on Configurator to provide executable code modules,
see ModuleManager).