1
1
import PicGo from '../core/PicGo'
2
2
import spawn from 'cross-spawn'
3
- import { IResult , IProcessEnv , Undefinable } from '../types'
4
- import { IBuildInEvent } from 'src/utils/enum'
3
+ import { IResult , IProcessEnv , Undefinable , IPluginProcessResult } from '../types'
4
+ import { IBuildInEvent } from '../utils/enum'
5
+ import { getProcessPluginName , getNormalPluginName } from '../utils/common'
5
6
6
7
class PluginHandler {
7
8
// Thanks to feflow -> https://github.com/feflow/feflow/blob/master/lib/internal/install/plugin.js
@@ -11,41 +12,89 @@ class PluginHandler {
11
12
}
12
13
13
14
async install ( plugins : string [ ] , proxy : string = '' , env ?: IProcessEnv ) : Promise < void > {
14
- plugins = plugins . map ( ( item : string ) => 'picgo-plugin-' + item )
15
- const result = await this . execCommand ( 'install' , plugins , this . ctx . baseDir , proxy , env )
16
- if ( ! result . code ) {
17
- plugins . forEach ( ( plugin : string ) => {
18
- this . ctx . pluginLoader . registerPlugin ( plugin )
15
+ const installedPlugins : string [ ] = [ ]
16
+ const processPlugins = plugins
17
+ . map ( ( item : string ) => handlePluginNameProcess ( this . ctx , item ) )
18
+ . filter ( ( item ) => {
19
+ // detect if has already installed
20
+ // or will cause error
21
+ if ( this . ctx . pluginLoader . hasPlugin ( item . pkgName ) ) {
22
+ installedPlugins . push ( item . pkgName )
23
+ this . ctx . log . success ( `PicGo has already installed ${ item . pkgName } ` )
24
+ return false
25
+ }
26
+ // if something wrong, filter it out
27
+ if ( ! item . success ) {
28
+ return false
29
+ }
30
+ return true
19
31
} )
20
- this . ctx . log . success ( '插件安装成功' )
21
- this . ctx . emit ( 'installSuccess' , {
22
- title : '插件安装成功' ,
23
- body : plugins
24
- } )
25
- } else {
26
- const err = `插件安装失败,失败码为${ result . code } ,错误日志为${ result . data } `
32
+ const fullNameList = processPlugins . map ( item => item . fullName )
33
+ const pkgNameList = processPlugins . map ( item => item . pkgName )
34
+ if ( fullNameList . length > 0 ) {
35
+ // install plugins must use fullNameList:
36
+ // 1. install remote pacage
37
+ // 2. install local pacage
38
+ const result = await this . execCommand ( 'install' , fullNameList , this . ctx . baseDir , proxy , env )
39
+ if ( ! result . code ) {
40
+ pkgNameList . forEach ( ( pluginName : string ) => {
41
+ this . ctx . pluginLoader . registerPlugin ( pluginName )
42
+ } )
43
+ this . ctx . log . success ( '插件安装成功' )
44
+ this . ctx . emit ( 'installSuccess' , {
45
+ title : '插件安装成功' ,
46
+ body : [ ...pkgNameList , ...installedPlugins ]
47
+ } )
48
+ } else {
49
+ const err = `插件安装失败,失败码为${ result . code } ,错误日志为${ result . data } `
50
+ this . ctx . log . error ( err )
51
+ this . ctx . emit ( 'installFailed' , {
52
+ title : '插件安装失败' ,
53
+ body : err
54
+ } )
55
+ }
56
+ } else if ( installedPlugins . length === 0 ) {
57
+ const err = '插件安装失败,请输入合法插件名或合法安装路径'
27
58
this . ctx . log . error ( err )
28
59
this . ctx . emit ( 'installFailed' , {
29
60
title : '插件安装失败' ,
30
61
body : err
31
62
} )
63
+ } else {
64
+ this . ctx . log . success ( '插件安装成功' )
65
+ this . ctx . emit ( 'installSuccess' , {
66
+ title : '插件安装成功' ,
67
+ body : [ ...pkgNameList , ...installedPlugins ]
68
+ } )
32
69
}
33
70
}
34
71
35
72
async uninstall ( plugins : string [ ] ) : Promise < void > {
36
- plugins = plugins . map ( ( item : string ) => 'picgo-plugin-' + item )
37
- const result = await this . execCommand ( 'uninstall' , plugins , this . ctx . baseDir )
38
- if ( ! result . code ) {
39
- plugins . forEach ( ( plugin : string ) => {
40
- this . ctx . pluginLoader . unregisterPlugin ( plugin )
41
- } )
42
- this . ctx . log . success ( '插件卸载成功' )
43
- this . ctx . emit ( 'uninstallSuccess' , {
44
- title : '插件卸载成功' ,
45
- body : plugins
46
- } )
73
+ const processPlugins = plugins . map ( ( item : string ) => handlePluginNameProcess ( this . ctx , item ) ) . filter ( item => item . success )
74
+ const pkgNameList = processPlugins . map ( item => item . pkgName )
75
+ if ( pkgNameList . length > 0 ) {
76
+ // uninstall plugins must use pkgNameList:
77
+ // npm uninstall will use the package.json's name
78
+ const result = await this . execCommand ( 'uninstall' , pkgNameList , this . ctx . baseDir )
79
+ if ( ! result . code ) {
80
+ pkgNameList . forEach ( ( pluginName : string ) => {
81
+ this . ctx . pluginLoader . unregisterPlugin ( pluginName )
82
+ } )
83
+ this . ctx . log . success ( '插件卸载成功' )
84
+ this . ctx . emit ( 'uninstallSuccess' , {
85
+ title : '插件卸载成功' ,
86
+ body : pkgNameList
87
+ } )
88
+ } else {
89
+ const err = `插件卸载失败,失败码为${ result . code } ,错误日志为${ result . data } `
90
+ this . ctx . log . error ( err )
91
+ this . ctx . emit ( 'uninstallFailed' , {
92
+ title : '插件卸载失败' ,
93
+ body : err
94
+ } )
95
+ }
47
96
} else {
48
- const err = ` 插件卸载失败,失败码为 ${ result . code } ,错误日志为 ${ result . data } `
97
+ const err = ' 插件卸载失败,请输入合法插件名'
49
98
this . ctx . log . error ( err )
50
99
this . ctx . emit ( 'uninstallFailed' , {
51
100
title : '插件卸载失败' ,
@@ -55,16 +104,28 @@ class PluginHandler {
55
104
}
56
105
57
106
async update ( plugins : string [ ] , proxy : string = '' , env ?: IProcessEnv ) : Promise < void > {
58
- plugins = plugins . map ( ( item : string ) => 'picgo-plugin-' + item )
59
- const result = await this . execCommand ( 'update' , plugins , this . ctx . baseDir , proxy , env )
60
- if ( ! result . code ) {
61
- this . ctx . log . success ( '插件更新成功' )
62
- this . ctx . emit ( 'updateSuccess' , {
63
- title : '插件更新成功' ,
64
- body : plugins
65
- } )
107
+ const processPlugins = plugins . map ( ( item : string ) => handlePluginNameProcess ( this . ctx , item ) ) . filter ( item => item . success )
108
+ const pkgNameList = processPlugins . map ( item => item . pkgName )
109
+ if ( pkgNameList . length > 0 ) {
110
+ // update plugins must use pkgNameList:
111
+ // npm update will use the package.json's name
112
+ const result = await this . execCommand ( 'update' , pkgNameList , this . ctx . baseDir , proxy , env )
113
+ if ( ! result . code ) {
114
+ this . ctx . log . success ( '插件更新成功' )
115
+ this . ctx . emit ( 'updateSuccess' , {
116
+ title : '插件更新成功' ,
117
+ body : pkgNameList
118
+ } )
119
+ } else {
120
+ const err = `插件更新失败,失败码为${ result . code } ,错误日志为 \n ${ result . data } `
121
+ this . ctx . log . error ( err )
122
+ this . ctx . emit ( 'updateFailed' , {
123
+ title : '插件更新失败' ,
124
+ body : err
125
+ } )
126
+ }
66
127
} else {
67
- const err = ` 插件更新失败,失败码为 ${ result . code } ,错误日志为 \n ${ result . data } `
128
+ const err = ' 插件更新失败,请输入合法插件名'
68
129
this . ctx . log . error ( err )
69
130
this . ctx . emit ( 'updateFailed' , {
70
131
title : '插件更新失败' ,
@@ -116,4 +177,32 @@ class PluginHandler {
116
177
}
117
178
}
118
179
180
+ /**
181
+ * transform the input plugin name or path string to valid result
182
+ * @param ctx
183
+ * @param nameOrPath
184
+ */
185
+ const handlePluginNameProcess = ( ctx : PicGo , nameOrPath : string ) : IPluginProcessResult => {
186
+ const res = {
187
+ success : false ,
188
+ fullName : '' ,
189
+ pkgName : ''
190
+ }
191
+ const result = getProcessPluginName ( nameOrPath , ctx . log )
192
+ if ( ! result ) {
193
+ return res
194
+ }
195
+ // first get result then do this process
196
+ // or some error will log twice
197
+ const pkgName = getNormalPluginName ( result , ctx . log )
198
+ if ( ! pkgName ) {
199
+ return res
200
+ }
201
+ return {
202
+ success : true ,
203
+ fullName : result ,
204
+ pkgName
205
+ }
206
+ }
207
+
119
208
export default PluginHandler
0 commit comments