diff --git a/docs/aliases.md b/docs/aliases.md index 4cac4c14..f49c7c86 100644 --- a/docs/aliases.md +++ b/docs/aliases.md @@ -1,5 +1,6 @@ --- title: Aliases +description: Define aliases for commands, flags, and bins --- ## Command Aliases diff --git a/docs/base_class.md b/docs/base_class.md index 8b00a43a..56ba5e4f 100644 --- a/docs/base_class.md +++ b/docs/base_class.md @@ -1,5 +1,6 @@ --- title: Custom Base Class +description: Create an extendable Command class --- Use inheritance to share functionality between common commands. Here is an example of a command base class that has some common shared flags. diff --git a/docs/command_discovery_strategies.md b/docs/command_discovery_strategies.md index 33cb91fa..bc5133b2 100644 --- a/docs/command_discovery_strategies.md +++ b/docs/command_discovery_strategies.md @@ -89,7 +89,7 @@ export const COMMANDS = { The `explicit` strategy is useful to those who can't rely on file paths because they've bundled their code (see [Bundling](#bundling)) but it can also be used if you simply prefer to be more explicit about your commands instead of relying on oclif "magically" finding commands from the file system. -It can also be leveraged to create or modify commands at runtime (e.g. internationalize messages at runtime or add flags to a command based on an API spec - see `oclif + dynamic commands` section below). +It can also be leveraged to create or modify commands at runtime (e.g. internationalize messages at runtime or add flags to a command based on an API spec - see [dynamic commands](#dynamic-commands) section below). #### Hooks @@ -123,10 +123,47 @@ That configuration is essentially telling oclif to look for an `INIT_HOOK` expor #### Bundling -**We do not support bundling** given the endless number of tools + configurations that could be used. But if you choose to use a bundler, like `esbuild` there are a couple hard requirements - you must have a package.json in your root directory and a `bin/run` or `bin/run.js` bin script. _This means that you will not be able to successfully bundle your entire CLI (src code, package.json, node_modules, etc) into a single file._ +**We do not support bundling** given the endless number of tools + configurations that could be used. But if you choose to use a bundler, like `esbuild`, there are a couple hard requirements - you must have a package.json in your root directory and a `bin/run` or `bin/run.js` bin script. _This means that you will not be able to successfully bundle your entire CLI (src code, package.json, node_modules, etc) into a single file._ -If you want to use a bundler, you can see this [example repo](https://github.com/oclif/plugin-test-esbuild/). +If you still want to use a bundler, you can reference this [example repo](https://github.com/oclif/plugin-test-esbuild/). +#### Dynamic Commands + +You can also use the `explicit` strategy if you want to manipulate or create commands at runtime. Please note that such usage of the `explicit` strategy **cannot** be used with an `oclif.manifest.json`, which will have significant performance implications for your CLI in production. + +Example: +```typescript +// src/index.ts +import {Command, Flags} from '@oclif/core' + +import Hello from './commands/hello' +import HelloWorld from './commands/hello/world' + +const dynamicCommands: Record = {} +if (process.env.DYNAMIC_COMMAND) { + dynamicCommands[process.env.DYNAMIC_COMMAND] = class extends Command { + static flags = { + flag1: Flags.boolean({description: 'flag1 description'}), + } + + async run(): Promise { + const {flags} = await this.parse(this.constructor as Command.Class) + this.log('hello from', this.id, flags) + } + } +} + +export const COMMANDS = { + hello: Hello, + 'hello:world': HelloWorld, + ...dynamicCommands, +} +``` + +``` +❯ DYNAMIC_COMMAND=foo:bar:baz bin/run.js foo bar baz --flag1 +hello from foo:bar:baz { flag1: true } +``` ### `single` Strategy diff --git a/docs/config.md b/docs/config.md index 4aa660fa..82367c97 100644 --- a/docs/config.md +++ b/docs/config.md @@ -1,86 +1,8 @@ --- -title: Configuration +title: Config --- -## Configuring oclif - -You can configure the behavior of oclif inside your CLI or plugin's package.json. All of the configuration options should be placed under the `oclif` section. For example: - -```json -{ - "name": "my-cli", - "version": "1.2.3", - "dependencies": { - "@oclif/core": "^3" - }, - "oclif": { - "bin": "mycli", - "dirname": "mycli", - "commands": "./dist/commands", - "topicSeparator": " " - } -} -``` - -Here's a list of all the options that you can configure. - -| Property | Description | -|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------| -| `additionalHelpFlags` | Array of flags that should trigger help output in addition to `--help` | -| `additionalVersionFlags` | Array of flags that should trigger version output in addition to `--version` | -| `aliases` | Aliases for the plugin. This is used to support legacy plugins that have been renamed | -| `bin` | CLI bin name (e.g. `sf`, `heroku`, `git`, etc...) | -| `binAliases` | An array of strings that will all execute the CLI's bin. See [Aliases](./aliases.md#bin-aliases) for more | -| `dirname` | Directory name to use when determining CLI's config, cache, and data directories. | -| `commands` | Where oclif can find command classes. See [Command Discovery Strategies](./command_discovery_strategies.md) for more | -| `description` | Description of your plugin or CLI to show in help | -| `devPlugins` | List of plugins that will only be loaded in development. See [Plugins](./plugins.md) for more | -| `exitCodes` | Configured exit codes. See [Exit Codes](#exit-codes) section below | -| `flexibleTaxonomy` | Set to true to enable [flexible taxonomy](./flexible_taxonomy.md) | -| `helpClass` | Location of compiled [custom help class](./help_classes.md) | -| `helpOptions` | Settings for configuring behavior of help output. See [Help Options](#help-options) section below | -| `hooks` | Register your plugin or CLI's hooks. See [hooks](./hooks.md) for more | -| `jitPlugins` | Register plugins that can be installed just in time. See [Just-in-Time Plugin Installation](./jit_plugins.md) for more | -| `macos` | Settings for building macos installer. See [Releasing](./releasing.md) for more | -| `nsisCustomization` | A path to a .nsis file that's used to customize the installer for Windows. See [nsis-custom](./nsis-installer_customization.md) for more | -| `plugins` | List of plugins that should be loaded. See [Plugins](./plugins.md) for more | -| `state` | Set the state of your CLI or plugin to be shown in help (e.g. `beta` will show `This CLI is in beta`) | -| `theme` | Path to theme file to include with your CLI. See [Themes](./themes.md) for more | -| `topicSeparator` | The separator to use between topics - only colons (`":"`) and spaces (`" "`) are supported | -| `topics` | Define your CLI's topics. See [Topics](./topics.md) for more | -| `windows` | Settings for building windows installer. See [Releasing](./releasing.md) for more | - -### Exit Codes - -You can configure the desired exit codes for the following errors: -- `default` - default exit code for any error. -- `failedFlagParsing` - exit code when oclif fails to parse a flag's value. -- `failedFlagValidation` - exit code when a flag fails it's own validation. -- `invalidArgsSpec` - exit code when a command defines an invalid `args` configuration. -- `nonExistentFlag` - exit code when user provides a non-existent flag. -- `requiredArgs` - exit code when user fails to provide a required arg. -- `unexpectedArgs` - exit code when user provides unexpected args to a command. - -### Help Options - -You can configure the behavior of the help output with the following: -- `docopts` - Use docopts as the usage. Defaults to true. -- `flagSortOrder` - Order in which to sort flags in help output. Can be `alphabetical` (default) or `none` (flags will appear in the order they were defined). -- `hideAliasesFromRoot` - If true, hide command aliases from the root help output. Defaults to false. -- `hideCommandSummaryInDescription` - By default, the command summary is show at the top of the help and as the first line in the command description. Repeating the summary in the command description improves readability especially for long command help output. If there is no `command.summary`, the first line of the description is treated as the summary. Some CLIs, especially with very simple commands, may not want the duplication. -- `maxWidth` - Maximum column width of the help output. -- `sections` - Only show the help for the specified sections. Defaults to all sections. -- `sendToStderr` - By default, the help output is sent to stdout. If this is true, it will be sent to stderr. -- `showFlagNameInTitle` - By default, titles show flag values as ``. Some CLI developers may prefer titles to show the flag name as the value. i.e. `--myflag=myflag` instead of `--myflag=`. An individual flag can set this using `flag.helpValue=flag.name`. -- `showFlagOptionsInTitle` - By default, option values on flags are shown in the flag's description. This is because long options list ruin the formatting of help. If a CLI knows all commands will not do this, it can be turned off at a help level using this property. An individual flag can set this using `flag.helpValue=options.join('|')`. -- `stripAnsi` - Strip ansi characters from help out to remove all formatting. -- `usageHeader` - Override the header for the `USAGE` section. - -If you want to further customize help, you can implement a [Custom Help Class](./help_classes.md). - -## The `Config` Class - -Inside a command, `this.config` provides useful properties you can use in your command. Here are a list of its methods and properties: +Inside a command, `this.config` provides access to the `Config` class, which contains useful properties and methods you can use in your command. Here are a list of its methods and properties: - **name** - name of CLI - **version** - Version of the CLI. diff --git a/docs/configuring_your_cli.md b/docs/configuring_your_cli.md new file mode 100644 index 00000000..11c41a13 --- /dev/null +++ b/docs/configuring_your_cli.md @@ -0,0 +1,78 @@ +--- +title: Configuring Your CLI +description: All about configuring oclif +--- + +You can configure the behavior of oclif inside your CLI or plugin's package.json. All of the configuration options should be placed under the `oclif` section. For example: + +```json +{ + "name": "my-cli", + "version": "1.2.3", + "dependencies": { + "@oclif/core": "^3" + }, + "oclif": { + "bin": "mycli", + "dirname": "mycli", + "commands": "./dist/commands", + "topicSeparator": " " + } +} +``` + +Here's a list of all the options that you can configure. + +| Property | Description | +|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------| +| `additionalHelpFlags` | Array of flags that should trigger help output in addition to `--help` | +| `additionalVersionFlags` | Array of flags that should trigger version output in addition to `--version` | +| `aliases` | Aliases for the plugin. This is used to support legacy plugins that have been renamed | +| `bin` | CLI bin name (e.g. `sf`, `heroku`, `git`, etc...) | +| `binAliases` | An array of strings that will all execute the CLI's bin. See [Aliases](./aliases.md#bin-aliases) for more | +| `dirname` | Directory name to use when determining CLI's config, cache, and data directories. | +| `commands` | Where oclif can find command classes. See [Command Discovery Strategies](./command_discovery_strategies.md) for more | +| `description` | Description of your plugin or CLI to show in help | +| `devPlugins` | List of plugins that will only be loaded in development. See [Plugins](./plugins.md) for more | +| `exitCodes` | Configured exit codes. See [Exit Codes](#exit-codes) section below | +| `flexibleTaxonomy` | Set to true to enable [flexible taxonomy](./flexible_taxonomy.md) | +| `helpClass` | Location of compiled [custom help class](./help_classes.md) | +| `helpOptions` | Settings for configuring behavior of help output. See [Help Options](#help-options) section below | +| `hooks` | Register your plugin or CLI's hooks. See [hooks](./hooks.md) for more | +| `jitPlugins` | Register plugins that can be installed just in time. See [Just-in-Time Plugin Installation](./jit_plugins.md) for more | +| `macos` | Settings for building macos installer. See [Releasing](./releasing.md) for more | +| `nsisCustomization` | A path to a .nsis file that's used to customize the installer for Windows. See [nsis-custom](./nsis-installer_customization.md) for more | +| `plugins` | List of plugins that should be loaded. See [Plugins](./plugins.md) for more | +| `state` | Set the state of your CLI or plugin to be shown in help (e.g. `beta` will show `This CLI is in beta`) | +| `theme` | Path to theme file to include with your CLI. See [Themes](./themes.md) for more | +| `topicSeparator` | The separator to use between topics - only colons (`":"`) and spaces (`" "`) are supported | +| `topics` | Define your CLI's topics. See [Topics](./topics.md) for more | +| `windows` | Settings for building windows installer. See [Releasing](./releasing.md) for more | + +### Exit Codes + +You can configure the desired exit codes for the following errors: +- `default` - default exit code for any error. +- `failedFlagParsing` - exit code when oclif fails to parse a flag's value. +- `failedFlagValidation` - exit code when a flag fails it's own validation. +- `invalidArgsSpec` - exit code when a command defines an invalid `args` configuration. +- `nonExistentFlag` - exit code when user provides a non-existent flag. +- `requiredArgs` - exit code when user fails to provide a required arg. +- `unexpectedArgs` - exit code when user provides unexpected args to a command. + +### Help Options + +You can configure the behavior of the help output with the following: +- `docopts` - Use docopts as the usage. Defaults to true. +- `flagSortOrder` - Order in which to sort flags in help output. Can be `alphabetical` (default) or `none` (flags will appear in the order they were defined). +- `hideAliasesFromRoot` - If true, hide command aliases from the root help output. Defaults to false. +- `hideCommandSummaryInDescription` - By default, the command summary is show at the top of the help and as the first line in the command description. Repeating the summary in the command description improves readability especially for long command help output. If there is no `command.summary`, the first line of the description is treated as the summary. Some CLIs, especially with very simple commands, may not want the duplication. +- `maxWidth` - Maximum column width of the help output. +- `sections` - Only show the help for the specified sections. Defaults to all sections. +- `sendToStderr` - By default, the help output is sent to stdout. If this is true, it will be sent to stderr. +- `showFlagNameInTitle` - By default, titles show flag values as ``. Some CLI developers may prefer titles to show the flag name as the value. i.e. `--myflag=myflag` instead of `--myflag=`. An individual flag can set this using `flag.helpValue=flag.name`. +- `showFlagOptionsInTitle` - By default, option values on flags are shown in the flag's description. This is because long options list ruin the formatting of help. If a CLI knows all commands will not do this, it can be turned off at a help level using this property. An individual flag can set this using `flag.helpValue=options.join('|')`. +- `stripAnsi` - Strip ansi characters from help out to remove all formatting. +- `usageHeader` - Override the header for the `USAGE` section. + +If you want to further customize help, you can implement a [Custom Help Class](./help_classes.md). diff --git a/docs/debugging.md b/docs/debugging.md index 8ed1f736..1700cda4 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -1,5 +1,6 @@ --- title: Debugging +description: How to access debug logs --- Use the [debug](https://github.com/visionmedia/debug) for debugging. The CLI uses this module for all of its debugging. If you set the environment variable `DEBUG=*` it will print all the debug output to the screen. diff --git a/docs/error_handling.md b/docs/error_handling.md index 97693f59..dfa70313 100644 --- a/docs/error_handling.md +++ b/docs/error_handling.md @@ -1,5 +1,6 @@ --- title: Error Handling +description: Customize error handling --- oclif handles intentionally - and unintentionally - thrown errors in two places. First in the `Command.catch` method and then, finally, in the `bin/run.js` `catch` handler where the Error is printed and the CLI exits. This error flow makes it possible for you to control and respond to errors that occur in your CLI as you see fit. diff --git a/docs/esm.md b/docs/esm.md index 97612bcb..df952136 100644 --- a/docs/esm.md +++ b/docs/esm.md @@ -1,5 +1,6 @@ --- title: ESM +description: Using ESM in oclif --- Version 3.0.0 of `@oclif/core` officially supports ESM plugin development and CJS/ESM interoperability, meaning that you can have a root plugin written with CJS and your plugins written in ESM or vice versa. diff --git a/docs/features.md b/docs/features.md index 9f770312..562b571e 100644 --- a/docs/features.md +++ b/docs/features.md @@ -38,6 +38,12 @@ Use lifecycle hooks to run functionality any time a CLI starts, or on custom tri You can opt-in to using the `--json` flag which will automatically suppress console logs and display the final result of the command as valid JSON output. This is very useful if you want your CLI to be used for scripting in CI/CD environments. See [JSON](https://oclif.io/docs/json). +### Flexible Taxonomy + +You can opt-in to what we call [flexible taxonomy](./flexible_taxonomy.md). When enabled, this features allows users to execute commands without adhering to your defined command taxonomy. + +This is a great way to make your CLI more user friendly, especially if you have long command names that can be hard for users to remember. For example, it might be hard for users to remember if the command is called `project deploy metadata start` or if it's called `project start deploy metadata` - with flexible taxonomy, both are valid! + ### TypeScript (or not) Everything in the core of oclif is written in TypeScript and the generator can build fully configured TypeScript CLIs or just plain JavaScript CLIs. By virtue of static properties in TypeScript the syntax is a bit cleaner in TypeScript — but everything will work no matter which language you choose. If you use plugins support, the CLI will automatically use `ts-node` to run the plugins making it easy and fast to use TypeScript with minimal-to-no boilerplate needed for any oclif CLI. diff --git a/docs/flag_inheritance.md b/docs/flag_inheritance.md index e9a1ab99..5b633bce 100644 --- a/docs/flag_inheritance.md +++ b/docs/flag_inheritance.md @@ -1,5 +1,6 @@ --- title: Flag Inheritance +description: How to share flags --- There are some instances where you might want to define a flag once for all of your commands. In this case you can add a base flag to an abstract base `Command` class. For example, diff --git a/docs/flexible_taxonomy.md b/docs/flexible_taxonomy.md index 09ae44c4..f62e6dfd 100644 --- a/docs/flexible_taxonomy.md +++ b/docs/flexible_taxonomy.md @@ -1,8 +1,9 @@ --- title: Flexible Taxonomy +description: Unlock new levels of user-friendliness --- -If you'd like for your customers to execute commands without adhereing to the defined command taxonomy, you can enable `flexibleTaxonomy` and add a hook to the `oclif` section of your package.json: +If you'd like for your customers to execute commands without adhering to the defined command taxonomy, you can enable `flexibleTaxonomy` and add a hook to the `oclif` section of your package.json: ```json { diff --git a/docs/jit_plugins.md b/docs/jit_plugins.md index e14af632..0dd8eb73 100644 --- a/docs/jit_plugins.md +++ b/docs/jit_plugins.md @@ -1,5 +1,6 @@ --- title: Just-in-Time Plugin Installation +description: Support for just-in-time plugin installation --- Sometimes you might want to have a plugin that isn't bundled in your CLI but gets installed the first time it's executed by the user - we call this just-in-time plugin installation, or JIT for short. This can be useful if you need to reduce the package size of your CLI while still allowing users access to all the plugins. diff --git a/docs/json.md b/docs/json.md index 44d2bea7..64176eee 100644 --- a/docs/json.md +++ b/docs/json.md @@ -1,5 +1,6 @@ --- title: JSON +description: Native support for `--json` flag --- If you want to use the `--json` flag to return JSON output to the user, then you can set the `enableJsonFlag` property on the `Command` class. diff --git a/docs/nsis-installer_customization.md b/docs/nsis-installer_customization.md index c8e40da1..950b7333 100644 --- a/docs/nsis-installer_customization.md +++ b/docs/nsis-installer_customization.md @@ -1,5 +1,6 @@ --- title: NSIS Installer Customization +description: Custom nsis installer script --- Sometimes you need to verify some dependencies, ensure there are no conflicting CLIs installed, or do some other custom logic before installing your CLI. For npm-scenarios, simply specify a `preinstall` script. But Windows installers don't include this script. You must instead write your own nsis modification to do these checks. See where this custom script gets placed in the installer in the [oclif/oclif](https://github.com/oclif/oclif/blob/b8d76af9290716ef69d8d1026f98041268306dfd/src/commands/pack/win.ts#L60) repo. diff --git a/docs/releasing.md b/docs/releasing.md index db5d3718..638ff258 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -1,5 +1,6 @@ --- title: Release +description: How to release your CLI --- There are 2 main strategies for releasing oclif CLIs: npm and standalone tarballs. You can publish to one or both. diff --git a/docs/single_command_cli.md b/docs/single_command_cli.md index 26faefd8..5520e60f 100644 --- a/docs/single_command_cli.md +++ b/docs/single_command_cli.md @@ -1,5 +1,6 @@ --- title: Single Command CLI +description: Configure CLI to be a single command --- Sometimes you may want your CLI's executable to also be the only command, similar to many bash utilities like `ls` or `cat`. diff --git a/docs/testing.md b/docs/testing.md index cdc209ca..b09837ef 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -1,5 +1,6 @@ --- title: Testing +description: How to test your CLI --- Testing in oclif can be done with any testing framework. You can run commands with `MyCommand.run()` which returns a promise you can wait on. diff --git a/docs/themes.md b/docs/themes.md index 2cce56ce..72afdcec 100644 --- a/docs/themes.md +++ b/docs/themes.md @@ -1,5 +1,6 @@ --- title: Themes +description: Make help output pretty --- oclif supports themes that you can ship with your CLI, which users can then override if they choose. diff --git a/docs/user_experience.md b/docs/user_experience.md index f3a539cf..8ca5c367 100644 --- a/docs/user_experience.md +++ b/docs/user_experience.md @@ -1,5 +1,6 @@ --- title: User Experience +description: Provided user-experience utilities --- oclif's philosophy is that developers should free to design any user experience that they want for their users. In other words, we try really hard to not make any UX decisions for you. diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 74079492..1e5af8de 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -46,7 +46,7 @@ module.exports = { showLastUpdateTime: true, editUrl: "https://github.com/oclif/oclif.github.io/tree/docs/docs/", path: "../docs", - sidebarPath: "../website/sidebars.json", + sidebarPath: "../website/sidebars.ts", }, blog: { path: "blog", @@ -76,7 +76,7 @@ module.exports = { position: "right", }, { - to: "docs/config", + to: "docs/api_reference", label: "API Reference", position: "right", }, diff --git a/website/sidebars.json b/website/sidebars.json deleted file mode 100644 index c816f968..00000000 --- a/website/sidebars.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "docs": { - "Getting Started": [ - "introduction", - "features", - "faqs", - "generator_commands", - "templates" - ], - "Architecture": ["command_execution", "plugin_loading"], - "API Reference": [ - "config", - "commands", - "args", - "flags", - "command_discovery_strategies", - "topics", - "topic_separator", - "hooks", - "plugins", - "help_classes", - "error_handling", - "json", - "performance" - ], - "How to": [ - "releasing", - "testing", - "running_programmatically", - "jit_plugins", - "aliases", - "nsis-installer_customization", - "base_class", - "user_experience", - "debugging", - "flexible_taxonomy", - "flag_inheritance", - "single_command_cli", - "esm", - "themes" - ], - "Also See": [ - "examples", - "external_links", - "related_repos", - "how_we_work", - "feedback" - ] - } -} diff --git a/website/sidebars.ts b/website/sidebars.ts new file mode 100644 index 00000000..c8a510c0 --- /dev/null +++ b/website/sidebars.ts @@ -0,0 +1,87 @@ +import type { SidebarsConfig } from "@docusaurus/plugin-content-docs"; +const sidebars: SidebarsConfig = { + docs: [ + { + label: "Getting Started", + type: "category", + collapsed: false, + items: [ + "introduction", + "features", + "faqs", + "generator_commands", + "templates", + ], + }, + { + label: "Guides", + type: "category", + collapsed: true, + link: { + type: "generated-index", + slug: "guides", + }, + items: [ + "aliases", + "base_class", + "configuring_your_cli", + "debugging", + "error_handling", + "esm", + "flag_inheritance", + "flexible_taxonomy", + "jit_plugins", + "json", + "nsis-installer_customization", + "releasing", + "running_programmatically", + "single_command_cli", + "testing", + "themes", + "user_experience", + ], + }, + { + label: "API Reference", + type: "category", + collapsed: true, + link: { + type: "generated-index", + slug: "api_reference", + }, + items: [ + "commands", + "args", + "flags", + "config", + "command_discovery_strategies", + "topics", + "topic_separator", + "hooks", + "plugins", + "help_classes", + "performance", + ], + }, + { + label: "Architecture", + type: "category", + collapsed: true, + items: ["command_execution", "plugin_loading"], + }, + { + label: "Also See", + type: "category", + collapsed: true, + items: [ + "examples", + "external_links", + "related_repos", + "how_we_work", + "feedback", + ], + }, + ], +}; + +export default sidebars;