@oclif/plugin-plugins
Version:
plugins plugin for oclif
150 lines (147 loc) • 6.86 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@oclif/core");
const validate = require("validate-npm-package-name");
const chalk = require("chalk");
const plugins_1 = require("../../plugins");
class PluginsInstall 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(PluginsInstall);
this.flags = flags;
if (flags.verbose)
this.plugins.verbose = true;
const aliases = this.config.pjson.oclif.aliases || {};
for (let name of argv) {
if (aliases[name] === null)
this.error(`${name} is blocked`);
name = aliases[name] || name;
const p = await this.parsePlugin(name);
let plugin;
await this.config.runHook('plugins:preinstall', {
plugin: p,
});
try {
if (p.type === 'npm') {
core_1.ux.action.start(`Installing plugin ${chalk.cyan(this.plugins.friendlyName(p.name) + '@' + p.tag)}`);
plugin = await this.plugins.install(p.name, {
tag: p.tag,
force: flags.force,
});
}
else {
core_1.ux.action.start(`Installing plugin ${chalk.cyan(p.url)}`);
plugin = await this.plugins.install(p.url, { force: flags.force });
}
}
catch (error) {
core_1.ux.action.stop(chalk.bold.red('failed'));
throw error;
}
core_1.ux.action.stop(`installed v${plugin.version}`);
}
}
/* eslint-enable no-await-in-loop */
async parsePlugin(input) {
// git ssh url
if (input.startsWith('git+ssh://') || input.endsWith('.git')) {
return { url: input, type: 'repo' };
}
const getNameAndTag = async (input) => {
var _b, _c;
const regexAtSymbolNotAtBeginning = /(?<!^)@/;
const [splitName, tag = 'latest'] = input.split(regexAtSymbolNotAtBeginning);
const name = splitName.startsWith('@') ? splitName : await this.plugins.maybeUnfriendlyName(splitName);
validateNpmPkgName(name);
if (this.flags.jit) {
const jitVersion = (_c = (_b = this.config.pjson.oclif) === null || _b === void 0 ? void 0 : _b.jitPlugins) === null || _c === void 0 ? void 0 : _c[name];
if (jitVersion) {
if (regexAtSymbolNotAtBeginning.test(input))
this.warn(`--jit flag is present along side a tag. Ignoring tag ${tag} and using the version specified in package.json (${jitVersion}).`);
return { name, tag: jitVersion };
}
this.warn(`--jit flag is present but ${name} is not a JIT plugin. Installing ${tag} instead.`);
return { name, tag };
}
return { name, tag };
};
// scoped npm package, e.g. @oclif/plugin-version
if (input.startsWith('@') && input.includes('/')) {
const { name, tag } = await getNameAndTag(input);
return { name, tag, type: 'npm' };
}
if (input.includes('/')) {
// github url, e.g. https://github.com/oclif/plugin-version
if (input.includes(':'))
return { url: input, type: 'repo' };
// github org/repo, e.g. oclif/plugin-version
return { url: `https://github.com/${input}`, type: 'repo' };
}
// unscoped npm package, e.g. my-oclif-plugin
// friendly plugin name, e.g. version instead of @oclif/plugin-version (requires `scope` to be set in root plugin's package.json)
const { name, tag } = await getNameAndTag(input);
return { name, tag, type: 'npm' };
}
}
exports.default = PluginsInstall;
_a = PluginsInstall;
PluginsInstall.description = `Installs a plugin into the CLI.
Can be installed from npm or a git url.
Installation of a user-installed plugin will override a core plugin.
e.g. If you have a core plugin that has a 'hello' command, installing a user-installed plugin with a 'hello' command will override the core plugin implementation. This is useful if a user needs to update core plugin functionality in the CLI without the need to patch and update the whole CLI.
`;
PluginsInstall.usage = 'plugins:install PLUGIN...';
PluginsInstall.examples = [
'$ <%= config.bin %> plugins:install <%- config.pjson.oclif.examplePlugin || "myplugin" %> ',
'$ <%= config.bin %> plugins:install https://github.com/someuser/someplugin',
'$ <%= config.bin %> plugins:install someuser/someplugin',
];
PluginsInstall.strict = false;
PluginsInstall.args = {
plugin: core_1.Args.string({ description: 'Plugin to install.', required: true }),
};
PluginsInstall.flags = {
help: core_1.Flags.help({ char: 'h' }),
verbose: core_1.Flags.boolean({ char: 'v' }),
force: core_1.Flags.boolean({
char: 'f',
description: 'Run yarn install with force flag.',
}),
jit: core_1.Flags.boolean({
hidden: true,
parse: async (input, ctx) => {
var _b;
if (input === false || input === undefined)
return input;
const requestedPlugins = ctx.argv.filter(a => !a.startsWith('-'));
if (requestedPlugins.length === 0)
return input;
const jitPluginsConfig = (_b = ctx.config.pjson.oclif.jitPlugins) !== null && _b !== void 0 ? _b : {};
if (Object.keys(jitPluginsConfig).length === 0)
return input;
const plugins = new plugins_1.default(ctx.config);
const nonJitPlugins = await Promise.all(requestedPlugins.map(async (plugin) => {
const name = await plugins.maybeUnfriendlyName(plugin);
return { name, jit: Boolean(jitPluginsConfig[name]) };
}));
const nonJitPluginsNames = nonJitPlugins.filter(p => !p.jit).map(p => p.name);
if (nonJitPluginsNames.length > 0) {
throw new core_1.Errors.CLIError(`The following plugins are not JIT plugins: ${nonJitPluginsNames.join(', ')}`);
}
return input;
},
}),
};
PluginsInstall.aliases = ['plugins:add'];
function validateNpmPkgName(name) {
if (!validate(name).validForNewPackages) {
throw new core_1.Errors.CLIError('Invalid npm package name.');
}
}