1
1
const path = require ( 'path' )
2
2
const fs = require ( 'fs' )
3
3
const LRU = require ( 'lru-cache' )
4
+ const chalk = require ( 'chalk' )
4
5
// Subs
5
6
const channels = require ( '../channels' )
6
7
// Connectors
@@ -47,14 +48,13 @@ const logoCache = new LRU({
47
48
// Local
48
49
let currentPluginId
49
50
let eventsInstalled = false
50
- let plugins = [ ]
51
- let pluginApi
52
51
let installationStep
53
- let projectId
52
+ let pluginsStore = new Map ( )
53
+ let pluginApiInstances = new Map ( )
54
54
55
- function list ( file , context , resetApi = true ) {
55
+ async function list ( file , context , resetApi = true ) {
56
56
const pkg = folders . readPackage ( file , context )
57
- plugins = [ ]
57
+ let plugins = [ ]
58
58
plugins = plugins . concat ( findPlugins ( pkg . devDependencies || { } ) )
59
59
plugins = plugins . concat ( findPlugins ( pkg . dependencies || { } ) )
60
60
@@ -66,11 +66,14 @@ function list (file, context, resetApi = true) {
66
66
plugins . unshift ( service )
67
67
}
68
68
69
- if ( resetApi ) resetPluginApi ( context )
69
+ pluginsStore . set ( file , plugins )
70
+
71
+ if ( resetApi || ! pluginApiInstances . get ( file ) ) await resetPluginApi ( { file } , context )
70
72
return plugins
71
73
}
72
74
73
- function findOne ( id , context ) {
75
+ function findOne ( { id, file } , context ) {
76
+ const plugins = getPlugins ( file )
74
77
return plugins . find (
75
78
p => p . id === id
76
79
)
@@ -90,54 +93,77 @@ function findPlugins (deps) {
90
93
)
91
94
}
92
95
93
- function resetPluginApi ( context ) {
94
- // Clean up
95
- if ( pluginApi ) {
96
- pluginApi . views . forEach ( r => views . remove ( r . id , context ) )
97
- pluginApi . ipcHandlers . forEach ( fn => ipc . off ( fn ) )
98
- }
99
- sharedData . unWatchAll ( )
100
-
101
- clientAddons . clear ( context )
102
- suggestions . clear ( context )
103
-
104
- setTimeout ( ( ) => {
105
- const projects = require ( './projects' )
106
- const project = projects . getCurrent ( context )
107
-
108
- pluginApi = new PluginApi ( {
109
- plugins
110
- } , context )
96
+ function getPlugins ( file ) {
97
+ const plugins = pluginsStore . get ( file )
98
+ if ( ! plugins ) return [ ]
99
+ return plugins
100
+ }
111
101
112
- if ( projects . getType ( project ) !== 'vue' ) return
113
-
114
- // Run Plugin API
115
- runPluginApi ( path . resolve ( __dirname , '../../' ) , context , 'ui-defaults' )
116
- plugins . forEach ( plugin => runPluginApi ( plugin . id , context ) )
117
- runPluginApi ( cwd . get ( ) , context , 'vue-cli-ui' )
118
- // Add client addons
119
- pluginApi . clientAddons . forEach ( options => clientAddons . add ( options , context ) )
120
- // Add views
121
- pluginApi . views . forEach ( view => views . add ( view , context ) )
122
-
123
- if ( ! project ) return
124
- projectId = project . id
125
- pluginApi . project = project
126
- if ( projectId !== project . id ) {
127
- callHook ( 'projectOpen' , [ project , projects . getLast ( context ) ] , context )
128
- } else {
129
- callHook ( 'pluginReload' , [ project ] , context )
102
+ function resetPluginApi ( { file } , context ) {
103
+ return new Promise ( ( resolve , reject ) => {
104
+ let pluginApi = pluginApiInstances . get ( file )
105
+ let projectId
130
106
131
- // View open hook
132
- const currentView = views . getCurrent ( )
133
- if ( currentView ) views . open ( currentView . id )
107
+ // Clean up
108
+ if ( pluginApi ) {
109
+ projectId = pluginApi . project && pluginApi . project . id
110
+ pluginApi . views . forEach ( r => views . remove ( r . id , context ) )
111
+ pluginApi . ipcHandlers . forEach ( fn => ipc . off ( fn ) )
134
112
}
135
- } )
113
+ sharedData . unWatchAll ( )
114
+
115
+ clientAddons . clear ( context )
116
+ suggestions . clear ( context )
117
+
118
+ // Cyclic dependency with projects connector
119
+ setTimeout ( ( ) => {
120
+ const projects = require ( './projects' )
121
+ const project = projects . getCurrent ( context )
122
+ const plugins = getPlugins ( file )
123
+
124
+ pluginApi = new PluginApi ( {
125
+ plugins,
126
+ file
127
+ } , context )
128
+ pluginApiInstances . set ( file , pluginApi )
129
+
130
+ if ( projects . getType ( project ) !== 'vue' ) return
131
+
132
+ // Run Plugin API
133
+ runPluginApi ( path . resolve ( __dirname , '../../' ) , pluginApi , context , 'ui-defaults' )
134
+ plugins . forEach ( plugin => runPluginApi ( plugin . id , pluginApi , context ) )
135
+ runPluginApi ( cwd . get ( ) , pluginApi , context , 'vue-cli-ui' )
136
+ // Add client addons
137
+ pluginApi . clientAddons . forEach ( options => clientAddons . add ( options , context ) )
138
+ // Add views
139
+ pluginApi . views . forEach ( view => views . add ( view , context ) )
140
+
141
+ if ( ! project ) return
142
+ pluginApi . project = project
143
+ if ( projectId !== project . id ) {
144
+ callHook ( {
145
+ id : 'projectOpen' ,
146
+ args : [ project , projects . getLast ( context ) ] ,
147
+ file
148
+ } , context )
149
+ } else {
150
+ callHook ( {
151
+ id : 'pluginReload' ,
152
+ args : [ project ] ,
153
+ file
154
+ } , context )
155
+
156
+ // View open hook
157
+ const currentView = views . getCurrent ( )
158
+ if ( currentView ) views . open ( currentView . id )
159
+ }
136
160
137
- return true
161
+ resolve ( true )
162
+ } )
163
+ } )
138
164
}
139
165
140
- function runPluginApi ( id , context , fileName = 'ui' ) {
166
+ function runPluginApi ( id , pluginApi , context , fileName = 'ui' ) {
141
167
let module
142
168
try {
143
169
module = loadModule ( `${ id } /${ fileName } ` , cwd . get ( ) , true )
@@ -149,7 +175,7 @@ function runPluginApi (id, context, fileName = 'ui') {
149
175
if ( module ) {
150
176
pluginApi . pluginId = id
151
177
module ( pluginApi )
152
- log ( 'Plugin API loaded for' , id )
178
+ log ( 'Plugin API loaded for' , id , chalk . grey ( pluginApi . cwd ) )
153
179
pluginApi . pluginId = null
154
180
}
155
181
@@ -160,7 +186,14 @@ function runPluginApi (id, context, fileName = 'ui') {
160
186
} catch ( e ) { }
161
187
}
162
188
163
- function callHook ( id , args , context ) {
189
+ function getApi ( folder ) {
190
+ const pluginApi = pluginApiInstances . get ( folder )
191
+ if ( ! pluginApi ) throw new Error ( `No plugin API available for ${ folder } ` )
192
+ return pluginApi
193
+ }
194
+
195
+ function callHook ( { id, args, file } , context ) {
196
+ const pluginApi = getApi ( file )
164
197
const fns = pluginApi . hooks [ id ]
165
198
log ( `Hook ${ id } ` , fns . length , 'handlers' )
166
199
fns . forEach ( fn => fn ( ...args ) )
@@ -287,7 +320,7 @@ function runInvoke (id, context) {
287
320
await invoke ( id , prompts . getAnswers ( ) , cwd . get ( ) )
288
321
}
289
322
// Run plugin api
290
- runPluginApi ( id , context )
323
+ runPluginApi ( id , getApi ( cwd . get ( ) ) , context )
291
324
installationStep = 'diff'
292
325
293
326
notify ( {
@@ -327,7 +360,7 @@ function update (id, context) {
327
360
args : [ id ]
328
361
} )
329
362
currentPluginId = id
330
- const plugin = findOne ( id , context )
363
+ const plugin = findOne ( { id , file : cwd . get ( ) } , context )
331
364
const { current, wanted } = await dependencies . getVersion ( plugin , context )
332
365
333
366
await updatePackage ( cwd . get ( ) , getCommand ( cwd . get ( ) ) , null , id )
@@ -343,11 +376,11 @@ function update (id, context) {
343
376
icon : 'done'
344
377
} )
345
378
346
- resetPluginApi ( context )
379
+ await resetPluginApi ( { file : cwd . get ( ) } , context )
347
380
dependencies . invalidatePackage ( id , context )
348
381
349
382
currentPluginId = null
350
- return findOne ( id )
383
+ return findOne ( { id , file : cwd . get ( ) } , context )
351
384
} )
352
385
}
353
386
@@ -387,17 +420,15 @@ async function updateAll (context) {
387
420
icon : 'done'
388
421
} )
389
422
390
- resetPluginApi ( context )
423
+ await resetPluginApi ( { file : cwd . get ( ) } , context )
391
424
392
425
return updatedPlugins
393
426
} )
394
427
}
395
428
396
- function getApi ( ) {
397
- return pluginApi
398
- }
429
+ async function callAction ( { id, params, file = cwd . get ( ) } , context ) {
430
+ const pluginApi = getApi ( file )
399
431
400
- async function callAction ( { id, params } , context ) {
401
432
context . pubsub . publish ( channels . PLUGIN_ACTION_CALLED , {
402
433
pluginActionCalled : { id, params }
403
434
} )
0 commit comments