@oclif/plugin-plugins
Version:
plugins plugin for oclif
149 lines (148 loc) • 6.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const core_1 = require("@oclif/core");
const chalk = require("chalk");
const promises_1 = require("fs/promises");
const plugins_1 = require("../../plugins");
const util_1 = require("../../util");
function trimUntil(fsPath, part) {
const parts = fsPath.split(path.sep);
const indices = parts.reduce((a, e, i) => (e === part) ? a.concat([i]) : a, []);
const partIndex = Math.max(...indices);
if (partIndex === -1)
return fsPath;
return parts.slice(0, partIndex + 1).join(path.sep);
}
class PluginsInspect extends core_1.Command {
constructor() {
super(...arguments);
this.plugins = new plugins_1.default(this.config);
}
// In this case we want these operations to happen
// sequentially so the `no-await-in-loop` rule is ignored
/* eslint-disable no-await-in-loop */
async run() {
const { flags, argv } = await this.parse(PluginsInspect);
if (flags.verbose)
this.plugins.verbose = true;
const aliases = this.config.pjson.oclif.aliases || {};
const plugins = [];
for (let name of argv) {
if (name === '.') {
const pkgJson = JSON.parse(await (0, promises_1.readFile)('package.json', 'utf-8'));
name = pkgJson.name;
}
if (aliases[name] === null)
this.error(`${name} is blocked`);
name = aliases[name] || name;
const pluginName = await this.parsePluginName(name);
try {
plugins.push(await this.inspect(pluginName, flags.verbose));
}
catch (error) {
this.log(chalk.bold.red('failed'));
throw error;
}
}
return plugins;
}
/* eslint-enable no-await-in-loop */
async parsePluginName(input) {
if (input.includes('@') && input.includes('/')) {
input = input.slice(1);
const [name] = input.split('@');
return '@' + name;
}
const [splitName] = input.split('@');
const name = await this.plugins.maybeUnfriendlyName(splitName);
return name;
}
findPlugin(pluginName) {
var _a;
const pluginConfig = this.config.getPluginsList().find(plg => plg.name === pluginName);
if (pluginConfig)
return pluginConfig;
if ((_a = this.config.pjson.oclif.jitPlugins) === null || _a === void 0 ? void 0 : _a[pluginName]) {
this.warn(`Plugin ${pluginName} is a JIT plugin. It will be installed the first time you run one of it's commands.`);
}
throw new Error(`${pluginName} not installed`);
}
async inspect(pluginName, verbose = false) {
var _a;
const plugin = this.findPlugin(pluginName);
const tree = core_1.ux.tree();
const pluginHeader = chalk.bold.cyan(plugin.name);
tree.insert(pluginHeader);
tree.nodes[pluginHeader].insert(`version ${plugin.version}`);
if (plugin.tag)
tree.nodes[pluginHeader].insert(`tag ${plugin.tag}`);
if (plugin.pjson.homepage)
tree.nodes[pluginHeader].insert(`homepage ${plugin.pjson.homepage}`);
tree.nodes[pluginHeader].insert(`location ${plugin.root}`);
tree.nodes[pluginHeader].insert('commands');
const commands = (0, util_1.sortBy)(plugin.commandIDs, c => c);
commands.forEach(cmd => tree.nodes[pluginHeader].nodes.commands.insert(cmd));
const dependencies = Object.assign({}, plugin.pjson.dependencies);
tree.nodes[pluginHeader].insert('dependencies');
const deps = (0, util_1.sortBy)(Object.keys(dependencies), d => d);
const depsJson = {};
for (const dep of deps) {
// eslint-disable-next-line no-await-in-loop
const { version, pkgPath } = await this.findDep(plugin, dep);
if (!version)
continue;
const from = (_a = dependencies[dep]) !== null && _a !== void 0 ? _a : null;
const versionMsg = chalk.dim(from ? `${from} => ${version}` : version);
const msg = verbose ? `${dep} ${versionMsg} ${pkgPath}` : `${dep} ${versionMsg}`;
tree.nodes[pluginHeader].nodes.dependencies.insert(msg);
depsJson[dep] = { from, version };
}
if (!this.jsonEnabled())
tree.display();
return Object.assign(Object.assign({}, plugin), { deps: depsJson });
}
async findDep(plugin, dependency) {
const dependencyPath = path.join(...dependency.split('/'));
let start = path.join(plugin.root, 'node_modules');
const paths = [start];
while ((start.match(/node_modules/g) || []).length > 1) {
start = trimUntil(path.dirname(start), 'node_modules');
paths.push(start);
}
// TODO: use promise.any to check the paths in parallel
// requires node >= 16
for (const p of paths) {
const fullPath = path.join(p, dependencyPath);
const pkgJsonPath = path.join(fullPath, 'package.json');
try {
// eslint-disable-next-line no-await-in-loop
const pkgJson = JSON.parse(await (0, promises_1.readFile)(pkgJsonPath, 'utf-8'));
return { version: pkgJson.version, pkgPath: fullPath };
}
catch (_a) {
// try the next path
}
}
return { version: null, pkgPath: null };
}
}
exports.default = PluginsInspect;
PluginsInspect.description = 'Displays installation properties of a plugin.';
PluginsInspect.usage = 'plugins:inspect PLUGIN...';
PluginsInspect.examples = [
'$ <%= config.bin %> plugins:inspect <%- config.pjson.oclif.examplePlugin || "myplugin" %> ',
];
PluginsInspect.strict = false;
PluginsInspect.enableJsonFlag = true;
PluginsInspect.args = {
plugin: core_1.Args.string({
description: 'Plugin to inspect.',
required: true,
default: '.',
}),
};
PluginsInspect.flags = {
help: core_1.Flags.help({ char: 'h' }),
verbose: core_1.Flags.boolean({ char: 'v' }),
};