-
Notifications
You must be signed in to change notification settings - Fork 22
/
install.ts
100 lines (83 loc) · 3.36 KB
/
install.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import {Command, Flags, CliUx} from '@oclif/core'
import * as chalk from 'chalk'
import Plugins from '../../plugins'
export default class PluginsInstall extends Command {
static 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.
`;
static usage = 'plugins:install PLUGIN...';
static 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',
];
static strict = false;
static args = [
{name: 'plugin', description: 'Plugin to install.', required: true},
];
static flags = {
help: Flags.help({char: 'h'}),
verbose: Flags.boolean({char: 'v'}),
force: Flags.boolean({
char: 'f',
description: 'Run yarn install with force flag.',
}),
};
static aliases = ['plugins:add'];
plugins = new Plugins(this.config);
// In this case we want these operations to happen
// sequentially so the `no-await-in-loop` rule is ugnored
/* eslint-disable no-await-in-loop */
async run(): Promise<void> {
const {flags, argv} = await this.parse(PluginsInstall)
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') {
CliUx.ux.action.start(
`Installing plugin ${chalk.cyan(this.plugins.friendlyName(p.name))}`,
)
plugin = await this.plugins.install(p.name, {
tag: p.tag,
force: flags.force,
})
} else {
CliUx.ux.action.start(`Installing plugin ${chalk.cyan(p.url)}`)
plugin = await this.plugins.install(p.url, {force: flags.force})
}
} catch (error) {
CliUx.ux.action.stop(chalk.bold.red('failed'))
throw error
}
CliUx.ux.action.stop(`installed v${plugin.version}`)
}
}
/* eslint-enable no-await-in-loop */
async parsePlugin(input: string): Promise<{name: string; tag: string; type: 'npm'} | {url: string; type: 'repo'}> {
if (input.startsWith('git+ssh://') || input.endsWith('.git')) {
return {url: input, type: 'repo'}
}
if (input.includes('@') && input.includes('/')) {
input = input.slice(1)
const [name, tag = 'latest'] = input.split('@')
return {name: '@' + name, tag, type: 'npm'}
}
if (input.includes('/')) {
if (input.includes(':')) return {url: input, type: 'repo'}
return {url: `https://github.com/${input}`, type: 'repo'}
}
const [splitName, tag = 'latest'] = input.split('@')
const name = await this.plugins.maybeUnfriendlyName(splitName)
return {name, tag, type: 'npm'}
}
}