-
Notifications
You must be signed in to change notification settings - Fork 27
Plugins
The Imperative CLI Framework contains features and components that let you develop plug-ins that you can use with Imperative-based CLI applications. Use the documentation in this section to learn about developing and managing CLI plug-ins.
Brandon/Jim not sure where this goes but this should be from the developer of an imperative cli based application. (and possibly someone who takes an imperative based cli application and calls the apis directly. So like the vscode extension would be an example.)
It also might be useful information to a developer of a plugin for an imperative cli so have fun figuring out where this goes.
When you enable plug-ins in Imperative Based CLIs, the Plugin Management Facility (PMF) initializes the Module Loader. The Module Loader provides the correct versions of the Imperative Framework and the Imperative-based CLI to the plug-in that you installed in your Imperative-based CLI.
To provide the correct version, the Module Loader overrides Module.prototype.require
, which also overrides require
. In short, the Module Loader performs the following actions:
- Stores the original mapping of
Module.prototype.require
for use at a later time. The Module Loader stores the mapping information in a variable namedoriginalRequire
. - Overrides
Module.prototype.require
with a custom method.
After the Module Loader initializes, all further require
calls undergo the following logic:
-
require
is intercepted by the Module Loader custom function. - The custom function checks if the require is for the Imperative-based CLI module or the Imperative module.
-
Note: When the require is for the Imperative-based CLI module or the Imperative module, the Module Loader remaps the require to the Imperative-based CLI module or the imperative module that is present in the
node_modules
of the Imperative-based CLI (injected modules).
-
Note: When the require is for the Imperative-based CLI module or the Imperative module, the Module Loader remaps the require to the Imperative-based CLI module or the imperative module that is present in the
- The
originalRequire
method is called and returned. Calling (and returning) the method helps to ensure thatrequire
returns the proper module information to the caller.
The above logic lets your plug-in get the injected modules from the runtime location rather than specifying them as a dependency. When you specify the modules as a dependency, the Module Loader never uses them, however, the Module Loader provides them as injected modules. As a best practice, we recommend that you specify the injected modules as a devDependency
only when you plan to use them.
The following example illustrates the structures and properties of an Imperative-based CLI and your installed plug-in.
Consider the following structure of an Imperative-based CLI:
-
/root
- /node_modules
- /@brightside/imperative
- /test-pkg
- package.json
- /lib
- main.js
- index.js
- /node_modules
-
Where plugins are enabled.
-
Where
/root/lib/index.js
is the application code. -
Where
/root/lib/main.js
is the cli entrypoint. -
Where
/root/package.json
contains:
{
"name": "some-package-name",
"bin": {
"cli-command": "./lib/main.js"
},
"main": "lib/index.js",
"dependencies": {
"test-pkg": "1.0.0",
"@brightside/imperative": "2.0.0"
}
}
Consider the following structure for your plug-in:
-
/plugin-root
- /node_modules
- /test-pkg
- /@brightside/imperative
- /some-package-name
- package.json
- index.js
- /node_modules
-
Where
/plugin-root/package.json
contains:
{
"name": "some-plugin-name",
"main": "index.js",
"dependencies": {
"test-pkg": "2.0.0"
},
"devDependencies": {
"@brightside/imperative": "2.0.0",
"some-package-name": "1.0.0"
}
}
- Where
/plugin-root/index.js
contains:
console.log(require.resolve("@brightside/imperative"));
console.log(require.resolve("@brightside/imperative/lib/error"));
console.log(require.resolve("some-package-name"));
console.log(require.resolve("some-package-name/lib/index"));
console.log(require.resolve("test-pkg"));
After you install the plug-in that you developed to the Imperative-based CLI, you can issue the following command to invoke /plugin-root/index.js
:
cli-command some-plugin-name
The following output displays.
Observe the difference between the output that displays when the Module Loader is disabled and when the Module Loader is enabled.
/plugin-root/node_modules/@brightside/imperative/lib/index.js
/plugin-root/node_modules/@brightside/imperative/lib/error/index.js
/plugin-root/node_modules/some-package-name/lib/index.js
/plugin-root/node_modules/some-package-name/lib/index.js
/plugin-root/node_modules/test-pkg/index.js
/root/node_modules/@brightside/imperative/lib/index.js
/root/node_modules/@brightside/imperative/lib/error/index.js
/root/lib/index.js
/root/lib/index.js
/plugin-root/node_modules/test-pkg/index.js
As illustrated by the above example, when the Module Loadter is disabled, all imports go to the /plugin-root/node_modules
folder. In other words, your plug-in must supply the injected modules (Imperative
and some-package-name
) that are already in the runtime.
When the Module Loader is enabled, the modules are loaded from the existing modules in the runtime. This lets you install your plug-in without having to install the injected modules, which can help reduce download time and consume less disk space. This is done by specifying the injected modules as devDependencies
in the package.json
for your plug-in, as illustrated in the setup above.
- Home
-
Core Features
- Imperative Configuration
- Defining Commands
- Command Handlers
- Command Option Precedence
- Environment Variables
- Help Generator
- Experimental Commands
- Creating Commands Using Chained Handlers
- Configuring Logging
- Working with Team Configuration
- Defining and Programming Profiles
- Managing Secure Properties
- Deprecated User Profiles
- Consuming REST APIs Using the REST Client
- Implementing Progress Bars
- Plugins