Docs: Generate CLI command references from file names instead of usage

Change-type: patch
This commit is contained in:
myarmolinsky 2024-09-30 13:56:48 -04:00
parent 0847daba1b
commit f52e6bd8b4
6 changed files with 206 additions and 231 deletions

View File

@ -26,7 +26,7 @@ export interface Document {
export interface Category {
title: string;
commands: OclifCommand[];
commands: Array<OclifCommand & { name: string }>;
}
export { OclifCommand };

View File

@ -18,7 +18,6 @@ import * as path from 'path';
import { getCapitanoDoc } from './capitanodoc';
import type { Category, Document, OclifCommand } from './doc-types';
import * as markdown from './markdown';
import { stripIndent } from '../../src/utils/lazy';
/**
* Generates the markdown document (as a string) for the CLI documentation
@ -39,7 +38,7 @@ export async function renderMarkdown(): Promise<string> {
};
for (const jsFilename of commandCategory.files) {
category.commands.push(...(await importOclifCommands(jsFilename)));
category.commands.push(await importOclifCommands(jsFilename));
}
result.categories.push(category);
}
@ -47,51 +46,23 @@ export async function renderMarkdown(): Promise<string> {
return markdown.render(result);
}
// Help is now managed via a plugin
// This fake command allows capitanodoc to include help in docs
class FakeHelpCommand {
description = stripIndent`
List balena commands, or get detailed help for a specific command.
async function importOclifCommands(jsFilename: string) {
const command = (await import(path.join(process.cwd(), jsFilename)))
.default as OclifCommand;
List balena commands, or get detailed help for a specific command.
`;
examples = [
'$ balena help',
'$ balena help login',
'$ balena help os download',
];
args = {
command: {
description: 'command to show help for',
},
};
usage = 'help [command]';
flags = {
verbose: {
description: 'show additional commands',
char: '-v',
},
};
}
async function importOclifCommands(
jsFilename: string,
): Promise<OclifCommand[]> {
// TODO: Currently oclif commands with no `usage` overridden will cause
// an error when parsed. This should be improved so that `usage` does not have
// to be overridden if not necessary.
const command: OclifCommand =
jsFilename === 'help'
? (new FakeHelpCommand() as unknown as OclifCommand)
: ((await import(path.join(process.cwd(), jsFilename)))
.default as OclifCommand);
return [command];
return {
...command,
// build/commands/device/index.js -> device
// build/commands/device/list.js -> device list
name: jsFilename
.split('/')
.slice(2)
.join(' ')
.split('.')
.slice(0, 1)
.join(' ')
.split(' index')[0],
} as Category['commands'][0];
}
/**

View File

@ -22,8 +22,8 @@ import { getManualSortCompareFunction } from '../../src/utils/helpers';
import { capitanoizeOclifUsage } from '../../src/utils/oclif-utils';
import type { Category, Document, OclifCommand } from './doc-types';
function renderOclifCommand(command: OclifCommand): string[] {
const result = [`## ${ent.encode(command.usage || '')}`];
function renderOclifCommand(command: Category['commands'][0]): string[] {
const result = [`## ${ent.encode(command.name || '')}`];
const description = (command.description || '')
.split('\n')
.slice(1) // remove the first line, which oclif uses as help header
@ -80,7 +80,7 @@ function renderToc(categories: Category[]): string[] {
result.push(
category.commands
.map((command) => {
const signature = capitanoizeOclifUsage(command.usage);
const signature = capitanoizeOclifUsage(command.name);
return `\t- [${ent.encode(signature)}](${getAnchor(signature)})`;
})
.join('\n'),

View File

@ -162,164 +162,164 @@ are encouraged to regularly update the balena CLI to the latest version.
- API Keys
- [](#)
- [](#)
- [](#)
- [api-key generate](#api-key-generate)
- [api-key revoke](#api-key-revoke)
- [api-keys](#api-keys)
- Apps
- [](#)
- [app create](#app-create)
- Authentication
- [](#)
- [](#)
- [](#)
- [login](#login)
- [logout](#logout)
- [whoami](#whoami)
- Blocks
- [](#)
- [block create](#block-create)
- Config
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [config generate](#config-generate)
- [config inject](#config-inject)
- [config read](#config-read)
- [config reconfigure](#config-reconfigure)
- [config write](#config-write)
- Deploy
- [](#)
- [](#)
- [build](#build)
- [deploy](#deploy)
- Devices
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [device deactivate](#device-deactivate)
- [device identify](#device-identify)
- [device](#device)
- [device init](#device-init)
- [device local-mode](#device-local-mode)
- [device move](#device-move)
- [device os-update](#device-os-update)
- [device pin](#device-pin)
- [device public-url](#device-public-url)
- [device purge](#device-purge)
- [device reboot](#device-reboot)
- [device register](#device-register)
- [device rename](#device-rename)
- [device restart](#device-restart)
- [device rm](#device-rm)
- [device shutdown](#device-shutdown)
- [device start-service](#device-start-service)
- [device stop-service](#device-stop-service)
- [device track-fleet](#device-track-fleet)
- [devices](#devices)
- [devices supported](#devices-supported)
- Environment Variables
- [](#)
- [](#)
- [](#)
- [](#)
- [env add](#env-add)
- [env rename](#env-rename)
- [env rm](#env-rm)
- [envs](#envs)
- Fleets
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [fleet create](#fleet-create)
- [fleet](#fleet)
- [fleet pin](#fleet-pin)
- [fleet purge](#fleet-purge)
- [fleet rename](#fleet-rename)
- [fleet restart](#fleet-restart)
- [fleet rm](#fleet-rm)
- [fleet track-latest](#fleet-track-latest)
- [fleets](#fleets)
- Local
- [](#)
- [](#)
- [local configure](#local-configure)
- [local flash](#local-flash)
- Logs
- [](#)
- [logs](#logs)
- Network
- [](#)
- [](#)
- [](#)
- [scan](#scan)
- [ssh](#ssh)
- [tunnel](#tunnel)
- Notes
- [](#)
- [notes](#notes)
- Organizations
- [](#)
- [orgs](#orgs)
- OS
- [](#)
- [](#)
- [](#)
- [](#)
- [](#)
- [os build-config](#os-build-config)
- [os configure](#os-configure)
- [os download](#os-download)
- [os initialize](#os-initialize)
- [os versions](#os-versions)
- Platform
- [](#)
- [](#)
- [join](#join)
- [leave](#leave)
- Preload
- [](#)
- [preload](#preload)
- Push
- [](#)
- [push](#push)
- Releases
- [](#)
- [](#)
- [](#)
- [](#)
- [releases &#60;fleet&#62;](#releases-fleet)
- [release finalize](#release-finalize)
- [release](#release)
- [release invalidate](#release-invalidate)
- [release validate](#release-validate)
- [releases](#releases)
- Settings
- [](#)
- [settings](#settings)
- SSH Keys
- [](#)
- [](#)
- [](#)
- [](#)
- [key add](#key-add)
- [key](#key)
- [key rm](#key-rm)
- [keys](#keys)
- Support
- [](#)
- [support](#support)
- Tags
- [](#)
- [](#)
- [](#)
- [tag rm](#tag-rm)
- [tag set](#tag-set)
- [tags](#tags)
- Utilities
- [](#)
- [util available-drives](#util-available-drives)
- Version
- [](#)
- [version](#version)
# API Keys
##
## api-key generate
Generate a new balenaCloud API key for the current user, with the given
name. The key will be logged to the console.
@ -339,7 +339,7 @@ the API key name
### Options
##
## api-key revoke
Revoke balenaCloud API keys with the given
comma-separated list of ids.
@ -359,7 +359,7 @@ the API key ids
### Options
##
## api-keys
Print a list of balenaCloud API keys.
@ -381,7 +381,7 @@ fleet name or slug (preferred)
# Apps
##
## app create
Create a new balena app.
@ -424,7 +424,7 @@ app device type (Check available types with `balena devices supported`)
# Authentication
##
## login
Login to your balena account.
@ -485,7 +485,7 @@ TCP port number of local HTTP login server (--web auth only)
Hides warning for experimental features
##
## logout
Logout from your balena account.
@ -493,7 +493,7 @@ Examples:
$ balena logout
##
## whoami
Get the username and email address of the currently logged in user.
@ -503,7 +503,7 @@ Examples:
# Blocks
##
## block create
Create a new balena block.
@ -546,7 +546,7 @@ block device type (Check available types with `balena devices supported`)
# Config
##
## config generate
Generate a config.json file for a device or fleet.
@ -656,7 +656,7 @@ custom key name assigned to generated provisioning api key
expiry date assigned to generated provisioning api key (format: YYYY-MM-DD)
##
## config inject
Inject a 'config.json' file to a balenaOS image file or attached SD card or
USB stick.
@ -681,7 +681,7 @@ the path to the config.json file to inject
path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
##
## config read
Read the 'config.json' file of a balenaOS image file or attached SD card or
USB stick.
@ -705,7 +705,7 @@ path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
produce JSON output instead of tabular output
##
## config reconfigure
Interactively reconfigure a balenaOS image file or attached media.
@ -736,7 +736,7 @@ show advanced commands
balenaOS version, for example "2.32.0" or "2.44.0+rev1"
##
## config write
Write a key-value pair to the 'config.json' file of a balenaOS image file or
attached SD card or USB stick.
@ -768,7 +768,7 @@ path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
# Deploy
##
## build
Use this command to build an image or a complete multicontainer project with
the provided docker daemon in your development machine or balena device.
@ -967,7 +967,7 @@ Docker host TLS certificate file
Docker host TLS key file
##
## deploy
Usage: `deploy <fleet> ([image] | --build [--source build-dir])`
@ -1194,7 +1194,7 @@ Docker host TLS key file
# Devices
##
## device deactivate
Deactivate a device.
@ -1218,7 +1218,7 @@ the UUID of the device to be deactivated
answer "yes" to all questions (non interactive use)
##
## device identify
Identify a device by making the ACT LED blink (Raspberry Pi).
@ -1234,7 +1234,7 @@ the uuid of the device to identify
### Options
##
## device
Show information about a single device.
@ -1266,7 +1266,7 @@ produce JSON output instead of tabular output
open device dashboard page
##
## device init
Register a new device in the selected fleet, download the OS image for the
fleet's default device type, configure the image and write it to an SD card.
@ -1351,7 +1351,7 @@ custom key name assigned to generated provisioning api key
expiry date assigned to generated provisioning api key (format: YYYY-MM-DD)
##
## device local-mode
Output current local mode status, or enable/disable local mode
for specified device.
@ -1383,7 +1383,7 @@ disable local mode
output boolean indicating local mode status
##
## device move
Move one or more devices to another fleet.
@ -1418,7 +1418,7 @@ comma-separated list (no blank spaces) of device UUIDs to be moved
fleet name or slug (preferred)
##
## device os-update
Start a Host OS update for a device.
@ -1454,7 +1454,7 @@ include pre-release balenaOS versions
answer "yes" to all questions (non interactive use)
##
## device pin
Pin a device to a release.
@ -1477,7 +1477,7 @@ the commit of the release for the device to get pinned to
### Options
##
## device public-url
This command will output the current public URL for the
specified device. It can also enable or disable the URL,
@ -1510,7 +1510,7 @@ disable the public URL
determine if public URL is enabled
##
## device purge
Purge data from a device.
This will clear the device's "/data" directory.
@ -1531,7 +1531,7 @@ comma-separated list (no blank spaces) of device UUIDs
### Options
##
## device reboot
Remotely reboot a device.
@ -1551,7 +1551,7 @@ the uuid of the device to reboot
force action if the update lock is set
##
## device register
Register a new device with a balena fleet.
@ -1590,7 +1590,7 @@ custom uuid
device type slug (run 'balena devices supported' for possible values)
##
## device rename
Rename a device.
@ -1613,7 +1613,7 @@ the new name for the device
### Options
##
## device restart
Restart containers on a device.
If the --service flag is provided, then only those services' containers
@ -1643,7 +1643,7 @@ comma-separated list (no blank spaces) of device UUIDs to restart
comma-separated list (no blank spaces) of service names to restart
##
## device rm
Remove one or more devices from balena.
@ -1668,7 +1668,7 @@ comma-separated list (no blank spaces) of device UUIDs to be removed
answer "yes" to all questions (non interactive use)
##
## device shutdown
Remotely shutdown a device.
@ -1688,7 +1688,7 @@ the uuid of the device to shutdown
force action if the update lock is set
##
## device start-service
Start containers on a device.
@ -1712,7 +1712,7 @@ comma-separated list (no blank spaces) of service names
### Options
##
## device stop-service
Stop containers on a device.
@ -1736,7 +1736,7 @@ comma-separated list (no blank spaces) of service names
### Options
##
## device track-fleet
Make a device track the fleet's pinned release.
@ -1752,7 +1752,7 @@ the uuid of the device to make track the fleet's release
### Options
##
## devices
List all of your devices.
@ -1790,7 +1790,7 @@ fleet name or slug (preferred)
produce JSON output instead of tabular output
##
## devices supported
List the supported device types (like 'raspberrypi3' or 'intel-nuc').
@ -1813,7 +1813,7 @@ produce JSON output instead of tabular output
# Environment Variables
##
## env add
Add an environment or config variable to one or more fleets, devices or
services, as selected by the respective command-line options. Either the
@ -1888,7 +1888,7 @@ suppress warning messages
service name
##
## env rename
Change the value of a configuration or environment variable for a fleet,
device or service, as selected by command-line options.
@ -1951,7 +1951,7 @@ select a device-specific variable instead of a fleet variable
select a service variable (may be used together with the --device option)
##
## env rm
Remove a configuration or environment variable from a fleet, device
or service, as selected by command-line options.
@ -2018,7 +2018,7 @@ select a service variable (may be used together with the --device option)
do not prompt for confirmation before deleting the variable
##
## envs
List the environment or configuration variables of a fleet, device or
service, as selected by the respective command-line options. (A service
@ -2095,7 +2095,7 @@ service name
# Fleets
##
## fleet create
Create a new balena fleet.
@ -2136,7 +2136,7 @@ handle of the organization the fleet should belong to
fleet device type (Check available types with `balena devices supported`)
##
## fleet
Display detailed information about a single fleet.
@ -2172,7 +2172,7 @@ open fleet dashboard page
produce JSON output instead of tabular output
##
## fleet pin
Pin a fleet to a release.
@ -2195,7 +2195,7 @@ the commit of the release for the fleet to get pinned to
### Options
##
## fleet purge
Purge data from all devices belonging to a fleet.
This will clear the fleet's '/data' directory.
@ -2223,7 +2223,7 @@ fleet name or slug (preferred)
### Options
##
## fleet rename
Rename a fleet.
@ -2258,7 +2258,7 @@ the new name for the fleet
### Options
##
## fleet restart
Restart all devices belonging to a fleet.
@ -2285,7 +2285,7 @@ fleet name or slug (preferred)
### Options
##
## fleet rm
Permanently remove a fleet.
@ -2319,7 +2319,7 @@ fleet name or slug (preferred)
answer "yes" to all questions (non interactive use)
##
## fleet track-latest
Make this fleet track the latest release.
@ -2336,7 +2336,7 @@ the slug of the fleet to make track the latest release
### Options
##
## fleets
List all your balena fleets.
@ -2355,7 +2355,7 @@ produce JSON output instead of tabular output
# Local
##
## local configure
Configure or reconfigure a balenaOS drive or image.
@ -2372,7 +2372,7 @@ path of drive or image to configure
### Options
##
## local flash
Flash a balenaOS image to a drive.
Image file may be one of: .img|.zip|.gz|.bz2|.xz
@ -2406,7 +2406,7 @@ answer "yes" to all questions (non interactive use)
# Logs
##
## logs
Show logs for a specific device.
@ -2463,7 +2463,7 @@ Only show system logs. This can be used in combination with --service.
# Network
##
## scan
Scan for balenaOS devices on your local network.
@ -2492,7 +2492,7 @@ scan timeout in seconds
produce JSON output instead of tabular output
##
## ssh
Start a shell on a local or remote device. If a service name is not provided,
a shell will be opened on the host OS.
@ -2557,7 +2557,7 @@ increase verbosity
bypass global proxy configuration for the ssh connection
##
## tunnel
Use this command to open local TCP ports that tunnel to listening sockets in a
balenaOS device.
@ -2610,7 +2610,7 @@ port mapping in the format <remotePort>[:[localIP:]localPort]
# Notes
##
## notes
Set or update a device note. If the note argument is not provided,
it will be read from stdin.
@ -2640,7 +2640,7 @@ device UUID
# Organizations
##
## orgs
list all the organizations that you are a member of.
@ -2652,7 +2652,7 @@ Examples:
# OS
##
## os build-config
Interactively generate a configuration file that can then be used as
non-interactive input by the 'balena os configure' command.
@ -2682,7 +2682,7 @@ show advanced configuration options
path to output JSON file
##
## os configure
Configure a previously downloaded balenaOS image for a specific device type
or fleet.
@ -2807,7 +2807,7 @@ custom key name assigned to generated provisioning api key
expiry date assigned to generated provisioning api key (format: YYYY-MM-DD)
##
## os download
Download an unconfigured OS image for the specified device type.
Check available device types with 'balena devices supported'.
@ -2862,7 +2862,7 @@ or 'recommended' (excludes pre-releases, will fail if only pre-release versions
or 'menu' (interactive menu, non-ESR versions),
or 'menu-esr' (interactive menu, ESR versions)
##
## os initialize
Initialize an os image for a device with a previously
configured operating system image and flash the
@ -2899,7 +2899,7 @@ Check `balena util available-drives` for available options.
answer "yes" to all questions (non interactive use)
##
## os versions
Show the available balenaOS versions for the given device type.
Check available types with `balena devices supported`.
@ -2929,7 +2929,7 @@ include pre-release balenaOS versions
# Platform
##
## join
Move a local device to a fleet on another balena server, causing
the device to "join" the new server. The device must be running balenaOS.
@ -2981,7 +2981,7 @@ fleet name or slug (preferred)
the interval in minutes to check for updates
##
## leave
Remove a local device from its balena fleet, causing the device to
"leave" the server it is provisioned on. This effectively makes the device
@ -3010,7 +3010,7 @@ the device IP or hostname
# Preload
##
## preload
Preload a release (service images/containers) from a balena fleet, and optionally
a balenaOS splash screen, in a previously downloaded '.img' balenaOS image file
@ -3118,7 +3118,7 @@ Docker host TLS key file
# Push
##
## push
Build release images on balenaCloud servers or on a local mode device.
@ -3345,7 +3345,7 @@ The notes for this release
# Releases
##
## release finalize
Finalize a release. Releases can be "draft" or "final", and this command
changes a draft release into a final release. Draft releases can be created
@ -3371,7 +3371,7 @@ the commit or ID of the release to finalize
### Options
##
## release
The --json option is recommended when scripting the output of this command,
because field names are less likely to change in JSON format and because it
@ -3401,7 +3401,7 @@ produce JSON output instead of tabular output
Return the release composition
##
## release invalidate
Invalidate a release.
@ -3422,7 +3422,7 @@ the commit or ID of the release to invalidate
### Options
##
## release validate
Validate a release.
@ -3442,7 +3442,7 @@ the commit or ID of the release to validate
### Options
## releases &#60;fleet&#62;
## releases
List all releases of the given fleet.
@ -3480,7 +3480,7 @@ produce JSON output instead of tabular output
# Settings
##
## settings
Use this command to display the current balena CLI settings.
@ -3492,7 +3492,7 @@ Examples:
# SSH Keys
##
## key add
Add an SSH key to the balenaCloud account of the logged in user.
@ -3531,7 +3531,7 @@ the path to the public key file
### Options
##
## key
Display a single SSH key registered in balenaCloud for the logged in user.
@ -3547,7 +3547,7 @@ balenaCloud ID for the SSH key
### Options
##
## key rm
Remove a single SSH key registered in balenaCloud for the logged in user.
@ -3570,7 +3570,7 @@ balenaCloud ID for the SSH key
answer "yes" to all questions (non interactive use)
##
## keys
List all SSH keys registered in balenaCloud for the logged in user.
@ -3582,7 +3582,7 @@ Examples:
# Support
##
## support
Grant or revoke balena support agent access to devices or fleets
on balenaCloud. (This command does not apply to openBalena.)
@ -3632,7 +3632,7 @@ length of time to enable support for, in (h)ours or (d)ays, e.g. 12h, 2d
# Tags
##
## tag rm
Remove a tag from a fleet, device or release.
@ -3674,7 +3674,7 @@ device UUID
release id
##
## tag set
Set a tag on a fleet, device or release.
@ -3727,7 +3727,7 @@ device UUID
release id
##
## tags
List all tags and their values for the specified fleet, device or release.
@ -3765,7 +3765,7 @@ release id
# Utilities
##
## util available-drives
List available drives which are usable for writing an OS image to.
Does not list system drives.
@ -3774,7 +3774,7 @@ Does not list system drives.
# Version
##
## version
Display version information for the balena CLI and/or Node.js. Note that the
balena CLI executable installers for Windows and macOS, and the standalone

View File

@ -14,9 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { Command } from '@oclif/core';
import { Help } from '@oclif/core';
import * as indent from 'indent-string';
import { getChalk } from './utils/lazy';
import type { ResolvableReturnType } from 'balena-sdk/typings/utils';
// Partially overrides standard implementation of help plugin
// https://github.com/oclif/plugin-help/blob/master/src/index.ts
@ -94,9 +96,9 @@ export default class BalenaHelp extends Help {
})
.filter((c): c is (typeof commands)[0] => !!c);
let usageLength = 0;
let cmdLength = 0;
for (const cmd of primaryCommands) {
usageLength = Math.max(usageLength, cmd.usage?.length || 0);
cmdLength = Math.max(cmdLength, cmd.id.length);
}
let additionalCmdSection: string[];
@ -110,16 +112,15 @@ export default class BalenaHelp extends Help {
// Find longest usage, and pad usage of first command in each category
// This is to ensure that both categories align visually
for (const cmd of additionalCommands) {
usageLength = Math.max(usageLength, cmd.usage?.length || 0);
cmdLength = Math.max(cmdLength, cmd.id.length);
}
if (
typeof primaryCommands[0].usage === 'string' &&
typeof additionalCommands[0].usage === 'string'
typeof primaryCommands[0].id === 'string' &&
typeof additionalCommands[0].id === 'string'
) {
primaryCommands[0].usage = primaryCommands[0].usage.padEnd(usageLength);
additionalCommands[0].usage =
additionalCommands[0].usage.padEnd(usageLength);
primaryCommands[0].id = primaryCommands[0].id.padEnd(cmdLength);
additionalCommands[0].id = additionalCommands[0].id.padEnd(cmdLength);
}
additionalCmdSection = [
@ -143,7 +144,7 @@ prevent exit with an error as per Deprecation Policy
See: https://git.io/JRHUW#deprecation-policy`,
],
];
globalOps[0][0] = globalOps[0][0].padEnd(usageLength);
globalOps[0][0] = globalOps[0][0].padEnd(cmdLength);
const { deprecationPolicyNote, reachingOut } =
require('./utils/messages') as typeof import('./utils/messages');
@ -183,15 +184,20 @@ See: https://git.io/JRHUW#deprecation-policy`,
return outLines.join('\n');
}
protected formatCommands(commands: any[]): string {
protected formatCommands(
commands: Array<
Command.Loadable | ResolvableReturnType<Command.Loadable['load']>
>,
): string {
if (commands.length === 0) {
return '';
}
const body = this.renderList(
commands
.filter((c) => c.usage != null && c.usage !== '')
.map((c) => [c.usage, this.formatDescription(c.description)]),
commands.map((c) => [
c.id.replaceAll(':', ' '),
this.formatDescription(c.description),
]),
{
spacer: '\n',
stripAnsi: this.opts.stripAnsi,

View File

@ -34,13 +34,11 @@ export const trackPromise = new Promise((resolve) => {
*/
const hook: Hook<'prerun'> = async function (options) {
const events = await import('../../events');
const usage: string | string[] | undefined = options.Command.usage;
const cmdSignature =
usage == null ? '*' : typeof usage === 'string' ? usage : usage.join(' ');
const cmd = options.Command.id;
// Intentionally do not await for the track promise here, in order to
// run the command tracking and the command itself in parallel.
trackResolve(events.trackCommand(cmdSignature));
trackResolve(events.trackCommand(cmd));
};
export default hook;