-
Notifications
You must be signed in to change notification settings - Fork 86
Using the Plugin Module Loader
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 therequire
to the Imperative-based CLI module or the imperative module that is present in thenode_modules
of the Imperative-based CLI (injected modules). -
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 the modules 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.
Imperative-based CLI Setup
Consider the following structure of an Imperative-based CLI:
- /root
- /node_modules
- /@brightside/imperative
- /test-pkg
- package.json
- /lib
- main.js
- index.js
- 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"
}
}
Your plug-in Setup
Consider the following structure for your plug-in:
- /plugin-root
- /node_modules
- /test-pkg
- /@brightside/imperative
- /some-package-name
- package.json
- index.js
- 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"));
Issuing the Test
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.
Module Loader Disabled
/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
Module Loader Enabled
/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
Comparison of Output
As illustrated by the above example, when the Module Loader 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.
-
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