-
Notifications
You must be signed in to change notification settings - Fork 27
Plugins
The Imperative CLI Framework contains features that let you develop plug-ins for use with an Imperative-based CLI application. 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 enabling plugins in an Imperative Based CLI (IBC), the Plugin Management Facility (PMF) will initialize the Module Loader (ML). The ML's purpose is to provide the correct version of Imperative and the IBC to a Plugin Installed in the IBC (PIIBC).
The ML does this by overriding Module.prototype.require
, which also overrides require
. In short the ML does the following:
- Stores the original mapping of
Module.protoype.require
for use later.- Stored in a variable called
originalRequire
for the purpose of explanation
- Stored in a variable called
- Overrides
Module.prototype.require
with a custom method.
After the ML has been initialized, all further require
calls will undergo the following logic:
-
require
is intercepted by the ML custom function. - The custom function will check if the
require
is for the IBC module or the Imperative module.- If this is the case, the ML will remap the require to either the IBC or the imperative present in the node_modules of the IBC. (I will referr to both these modules as Injected Modules here forward)
- The
originalRequire
method is called and returned. This ensures thatrequire
returns the proper module information to the caller.
What this allows is for the PIIBC to get the Injected Modules from the runtime location. This means that the PIIBC does not have to specify Imperative or the IBC as a dependency. If these are specified as a dependency, they will never be used as the ML will still provide them as Injected Modules. It is recommended to specify the Injected Modules as a devDependency if you plan to use them.
This is an example of a possible IBC and PIIBC combination.
Suppose you have this IBC structure:
-
/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"
}
}
The PIIBC could have this structure:
-
/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 installing the PIIBC to the IBC, say you issue the following command to invoke /plugin-root/index.js
:
cli-command some-plugin-name
You would see the following output. Notice the difference in output with the ML disabled vs. 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 you can see above, when the ML is disabled, all imports will go to the /plugin-root/node_modules
folder. This means that the PIIBC must supply the Injected Modules (Imperative
and some-package-name
) that are already in the runtime.
With the ML enabled, those existing modules are loaded from the existing ones in the runtime. This allows the PIIBC to install without needing to install the Injected Modules as well, saving some download time and disk space. This is done by specifying the Injected Modules as devDependencies
in the PIIBC's package.json
as seen 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