aki-plugin-manager
v1.3.3
Published
Lightweight at-runtime plugin manager and loader
Downloads
149
Maintainers
Readme
aki-plugin-manager
Aki is a fast, lightweight plugin manager for Node.js applications. It supports finding, downloading, and loading packages dynamically at runtime.
Aki currently only retrieves packages from npm, although alternative sources may be added in the future.
Usage
Install a package
install = (
name: string, // package name on npm
version: string, // package version, e.g. "1.2.3" or "latest"
baseDir: string, // directory to save plugins
callback: (error?: Error) => void // called after installation
): Promise<void>
import aki from "aki-plugin-manager";
const dir = path.join(process.env.XDG_CONFIG_HOME, "myapp", "plugins");
aki.install("is-number", "latest", dir, () => console.log("installed!"));
List installed packages
list = (
baseDir: string // directory where plugins are saved
): [string, string][] // installed packages as [name, version]
import aki from "aki-plugin-manager";
const dir = path.join(process.env.XDG_CONFIG_HOME, "myapp", "plugins");
aki.list(dir); // [["is-number", "7.0.0"]]
Load installed package
load = (
baseDir: string, // directory where plugins are saved
name: string, // name of package to load
requireFn = require // (optional) specify a require function
): any
import aki from "aki-plugin-manager";
const dir = path.join(process.env.XDG_CONFIG_HOME, "myapp", "plugins");
const mymod = aki.load(dir, "mypackage");
mymod.sayHi();
Note: Specifying a require function may be necessary if you are using webpack, or if you want to load a plugin in Electron's renderer thread. See the Webpack Usage and Electron Usage sections.
Searching for packages
search = (
text: string = "", // (optional) query text
scope: string = "", // (optional) package scope on the registry
limit: number = 100 // (optional) max number of results
): Promise<RegistrySearchResults>
import aki from "aki-plugin-manager";
aki.search({ text: "foo" }).then((results: RegistrySearchResults) => {
if (results.total > 0) {
console.log(results.objects[0].package.name);
}
});
Unload package
unload = (
baseDir: string, // directory where plugins are saved
name: string, // name of loaded package
requireFn = require // (optional) specify a require function
): void
import aki from "aki-plugin-manager";
const dir = path.join(process.env.XDG_CONFIG_HOME, "myapp", "plugins");
const mymod = aki.load(dir, "mypackage");
mymod.sayHi();
aki.unload(dir, "mypackage");
Uninstall package
uninstall = (
name: string, // name of installed package
baseDir: string, // directory where plugins are saved
callback: () => void // called after uninstallation
): void
import aki from "aki-plugin-manager";
const dir = path.join(process.env.XDG_CONFIG_HOME, "myapp", "plugins");
aki.uninstall("is-number", dir, () => console.log("uninstalled!"));
With Other Tools
Webpack Usage
Webpack attempts to rewrite require
statements at compile time, which means
that if you try to load a plugin with a name or directory set at runtime,
you will likely get a "module not found" error even if it is referencing
the correct path.
To get around this, we need to keep webpack from attempting to rewrite the require function. The easiest way, although not best-practice, is with exec:
aki.load(dir, "mypackage", exec("require"));
Alternatively, depending on your module system, you may be able to use:
aki.load(dir, "mypackage", module[`require`].bind(module));
You may also be able to update your webpack config. Add
IgnorePlugin to specify a
regex pattern for which webpack won't rewrite the require
call.
Electron Usage
The recommended way to use Aki with Electron is by performing all actions in the main thread and communicating input/output through ipc. You can create ipcMain handlers in the main thread to accomplish this.
You might also be able to pass remote.require
as the requireFn for
aki.load
. This is very discouraged, particularly because remote
is
deprecated and you will likely have issues resolving plugin functions.
Building
npm install
npm run build
Testing
npm run test