-
Notifications
You must be signed in to change notification settings - Fork 0
/
uninstall.ts
135 lines (120 loc) · 4.29 KB
/
uninstall.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { Args, Flags, flush, handle } from '@oclif/core'
import { eachSeries } from 'async'
import { isPluginInstalled, Vault } from 'obsidian-utils'
import { UninstallArgs, UninstallFlags } from '../../commands'
import FactoryCommand, { FactoryFlags } from '../../providers/command'
import { Plugin, safeLoadConfig } from '../../providers/config'
import { pluginsSelector, removePluginDir } from '../../providers/plugins'
import { vaultsSelector } from '../../providers/vaults'
import { VAULTS_PATH_FLAG_DESCRIPTION } from '../../utils/constants'
import { logger } from '../../utils/logger'
/**
* Uninstall command removes specified plugins from vaults.
*/
export default class Uninstall extends FactoryCommand {
static readonly aliases = ['pu', 'plugins uninstall']
static override readonly description = `Uninstall plugin(s) from vaults.`
static override readonly examples = [
'<%= config.bin %> <%= command.id %> --path=/path/to/vaults',
'<%= config.bin %> <%= command.id %> --path=/path/to/vaults/*/.obsidian',
'<%= config.bin %> <%= command.id %> --path=/path/to/vaults/**/.obsidian',
'<%= config.bin %> <%= command.id %> id',
]
static override readonly flags = {
path: Flags.string({
char: 'p',
description: VAULTS_PATH_FLAG_DESCRIPTION,
default: '',
}),
...this.commonFlags,
}
static override readonly args = {
pluginId: Args.string({
description: 'Specific Plugin ID to install',
required: false,
}),
}
/**
* Executes the command.
* Parses the arguments and flags, and calls the action method.
* Handles errors and ensures flushing of logs.
*/
public async run() {
try {
const { args, flags } = await this.parse(Uninstall)
await this.action(args, this.flagsInterceptor(flags))
} catch (error) {
this.handleError(error)
} finally {
flush()
}
}
/**
* Main action method for the command.
* Loads vaults, selects vaults, and uninstall specified plugins.
* @param {UninstallArgs} args - The arguments passed to the command.
* @param {FactoryFlags} flags - The flags passed to the command.
* @returns {Promise<void>}
*/
private async action(
args: UninstallArgs,
flags: FactoryFlags<UninstallFlags>,
): Promise<void> {
const { path } = flags
const {
success: loadConfigSuccess,
data: config,
error: loadConfigError,
} = await safeLoadConfig(flags.config)
if (!loadConfigSuccess) {
logger.error('Failed to load config', { error: loadConfigError })
process.exit(1)
}
const vaults = await this.loadVaults(path)
const selectedVaults = await vaultsSelector(vaults)
// Check if pluginId is provided and uninstall only that plugin
const { pluginId } = args
if (pluginId) {
await this.uninstallPluginInVaults(selectedVaults, pluginId)
} else {
const selectedPlugins = await pluginsSelector(config.plugins)
await this.uninstallPluginsInVaults(selectedVaults, selectedPlugins)
}
}
private async uninstallPluginsInVaults(vaults: Vault[], plugins: Plugin[]) {
const uninstallVaultIterator = async (vault: Vault) => {
logger.debug(`Uninstall plugins for vault`, { vault })
const uninstalledPlugins = []
const failedPlugins = []
for (const stagePlugin of plugins) {
const childLogger = logger.child({ plugin: stagePlugin, vault })
if (!(await isPluginInstalled(stagePlugin.id, vault.path))) {
childLogger.warn(`Plugin not installed`)
continue
}
try {
await removePluginDir(stagePlugin.id, vault.path)
uninstalledPlugins.push(stagePlugin)
} catch (error) {
failedPlugins.push(stagePlugin)
childLogger.error(`Failed to uninstall plugin`, { error })
}
}
if (uninstalledPlugins.length) {
logger.info(`Uninstalled ${uninstalledPlugins.length} plugins`, {
vault,
})
}
return { uninstalledPlugins, failedPlugins }
}
eachSeries(vaults, uninstallVaultIterator, (error) => {
if (error) {
logger.debug('Error installing plugins', { error })
handle(error)
}
})
}
private async uninstallPluginInVaults(vaults: Vault[], id: string) {
await this.uninstallPluginsInVaults(vaults, [{ id }])
}
}