Extending
Create CLI commands
A command is a handler for a command-line cause. With the Node CLI adapter enabled, you declare commands with @Command (or defineCommand), read parsed arguments and flags off the event, and return output. The domain and its services are the same ones your HTTP routes use.
#Enable the adapter
Commands need @stone-js/node-cli-adapter. Add @NodeConsole() (or the blueprint) to the manifest; the adapter page covers setup. This page is the command author's deep reference.
#Declaring a command
import { Command } from '@stone-js/node-cli-adapter'
@Command({
name: 'tasks:import',
alias: 'import',
args: ['<file>', '[--dry-run]'],
description: 'Import tasks from a CSV file.'
})
export class ImportCommand {
constructor ({ tasks, logger }: { tasks: TaskService, logger: ILogger }) {
this.tasks = tasks; this.logger = logger
}
async handle (event: NodeCliEvent) {
const file = event.get<string>('file') // positional <file>
const dryRun = event.get<boolean>('dry-run', false) // flag
const rows = await readCsv(file)
if (dryRun) return `Would import ${rows.length} tasks`
rows.forEach((r) => this.tasks.add(r.title))
this.logger.info('imported', { count: rows.length })
return `Imported ${rows.length} tasks`
}
}import { defineCommand } from '@stone-js/node-cli-adapter'
const ImportCommand = ({ tasks }) => ({
handle: async (event) => {
const rows = await readCsv(event.get('file'))
rows.forEach((r) => tasks.add(r.title))
return `Imported ${rows.length} tasks`
}
})
export const commands = [
defineCommand(ImportCommand, {
name: 'tasks:import',
args: ['<file>', '[--dry-run]'],
description: 'Import tasks from a CSV file.'
}, true)
]#Arguments and flags
Declare inputs in args; the adapter parses them and puts them on the event, read with event.get() like any intention. The conventions:
| Syntax | Type | Description |
|---|---|---|
| <file> | required positional | A required argument; the command errors without it. |
| [file] | optional positional | An optional argument. |
| [--dry-run] | boolean flag | A flag, read as a boolean. |
| [--limit=<n>] | valued flag | A flag that carries a value. |
#Command options
| Option | Type | Description |
|---|---|---|
| name* | string | The command name, e.g. "tasks:import". |
| alias | string | string[] | Alternative name(s). |
| args | string | string[] | Declared arguments and flags. |
| description | string | Shown in help output. |
#Output
Return a string (or structured data) and the adapter writes it out; throw a domain error and it is reported with a non-zero exit, mapped the same way HTTP errors are. Use the injected logger for progress, the return value for the result.
node app tasks:import ./seed.csv --dry-run
node app import ./seed.csv # via the alias