npm @oclif/core 3.21.0

latest releases: 4.0.32, 4.0.31, 4.0.30...
8 months ago

Features

  • add strategies for command discovery (#945) (eaf5a86)

Command Discovery Strategies

Support three strategies for command discovery:

  1. pattern - this is the current behavior that finds commands based on glob patterns
  2. explicit - find commands that are exported from a specified file. This is to support developers who wish to bundle their CLI into a single file.
  3. single - CLI contains a single command executed by top-level bin
pattern Strategy

For pattern, plugins could continue to do this:

{
  "oclif": {
    "commands": "./dist/commands",
  }
}

which will tell oclif to look for commands in that directory (this is skipped if an oclif.manifest.json is present)

Alternatively, plugins could set this configuration:

{
  "oclif": {
    "commands": {
      "strategy": "pattern",
      "target": "./dist/commands"
    }
  }
}

And they could even add globPatterns to override the glob patterns that oclif uses when searching for command files:

{
  "oclif": {
    "commands": {
      "strategy": "pattern",
      "target": "./dist/commands",
      "globPatterns": [
         "**/*.+(js|cjs|mjs|ts|tsx|mts|cts)",
        "!**/*.+(d.*|test.*|spec.*|helpers.*)?(x)"
      ]
    }
  }
}
explicit Strategy

For explicit, plugins would add a new file (e.g. src/commands.ts) and then add this configuration to the package.json

{
  "oclif": {
    "commands": {
      "strategy": "explicit",
      "target": "./dist/index.js",
      "identifier": "COMMANDS",
    }
  }
}

src/index.ts would then need to have an export with the same name as the identifier (if not set, it defaults to default) that's an object of command names to command classes, e.g.

import Hello from './commands/hello'
import HelloWorld from './commands/hello/world'

export const COMMANDS = {
  hello: Hello,
  'hello:world': HelloWorld,
  howdy: Hello, // alias the `hello` command to `howdy`
}

The explicit strategy is useful to those who can't rely on file paths because they've bundled their code (oclif/oclif#653) 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. add flags to a command based on an API spec - see oclif + dynamic commands section below).

Unfortunately, there is no notable performance improvement for development since most of the time is spent auto-transpiling typescript with ts-node

single Strategy

This strategy is for single command CLIs, i.e. CLIs whose bin invokes a single command.

The current way to achieve this to set this in the package.json

{
  "oclif": {
    "default": ".",
    "commands": "./dist",
  }
}

The default tells oclif to use . as the command id when no command is found and commands tells oclif where to find the command file. In the example, ./dist will resolve to to ./dist/index.js

The default property has always been a less-than-ideal workaround and will be deprecated in favor of these settings:

{
  "oclif": {
    "commands": {
      "strategy": "single",
      "target": "./dist"
    }
  }
}
Note about oclif.manifest.json

For all strategies, the oclif.manifest.json will be used to load the commands instead of the default behavior of the strategy.

Don't miss a new core release

NewReleases is sending notifications on new releases.