Skip to content

Commit abd7306

Browse files
author
Guillaume Chau
committed
refactor(ui): plugins connector is now multi-project
1 parent 090c52d commit abd7306

File tree

10 files changed

+169
-116
lines changed

10 files changed

+169
-116
lines changed

packages/@vue/cli-ui/apollo-server/api/PluginApi.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const sharedData = require('../connectors/shared-data')
55
const views = require('../connectors/views')
66
const suggestions = require('../connectors/suggestions')
77
const folders = require('../connectors/folders')
8-
const cwd = require('../connectors/cwd')
98
const progress = require('../connectors/progress')
109
// Utils
1110
const ipc = require('../util/ipc')
@@ -22,12 +21,13 @@ const { validateSuggestion } = require('./suggestion')
2221
const { validateProgress } = require('./progress')
2322

2423
class PluginApi {
25-
constructor ({ plugins }, context) {
24+
constructor ({ plugins, file }, context) {
2625
// Context
2726
this.context = context
2827
this.pluginId = null
2928
this.project = null
3029
this.plugins = plugins
30+
this.cwd = file
3131
// Hooks
3232
this.hooks = {
3333
projectOpen: [],
@@ -362,8 +362,7 @@ class PluginApi {
362362
*/
363363
hasPlugin (id) {
364364
if (['vue-router', 'vuex'].includes(id)) {
365-
const folder = cwd.get()
366-
const pkg = folders.readPackage(folder, this.context, true)
365+
const pkg = folders.readPackage(this.cwd, this.context, true)
367366
return ((pkg.dependencies && pkg.dependencies[id]) || (pkg.devDependencies && pkg.devDependencies[id]))
368367
}
369368
return this.plugins.some(p => matchesPluginId(id, p.id))
@@ -402,15 +401,15 @@ class PluginApi {
402401
* Get current working directory.
403402
*/
404403
getCwd () {
405-
return cwd.get()
404+
return this.cwd()
406405
}
407406

408407
/**
409408
* Resolves a file relative to current working directory
410409
* @param {string} file Path to file relative to project
411410
*/
412411
resolve (file) {
413-
return path.resolve(cwd.get(), file)
412+
return path.resolve(this.cwd, file)
414413
}
415414

416415
/**

packages/@vue/cli-ui/apollo-server/connectors/configurations.js

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const fileTypes = ['js', 'json', 'yaml']
1818
let current = {}
1919

2020
function list (context) {
21-
return plugins.getApi().configurations
21+
return plugins.getApi(cwd.get()).configurations
2222
}
2323

2424
function findOne (id, context) {
@@ -183,13 +183,17 @@ async function getPromptTabs (id, context) {
183183
}
184184
await prompts.start()
185185

186-
plugins.callHook('configRead', [{
187-
config,
188-
data,
189-
onReadData,
190-
tabs,
191-
cwd: cwd.get()
192-
}], context)
186+
plugins.callHook({
187+
id: 'configRead',
188+
args: [{
189+
config,
190+
data,
191+
onReadData,
192+
tabs,
193+
cwd: cwd.get()
194+
}],
195+
file: cwd.get()
196+
}, context)
193197

194198
return tabs
195199
}
@@ -252,12 +256,16 @@ async function save (id, context) {
252256

253257
writeData({ config, data, changedFields }, context)
254258

255-
plugins.callHook('configWrite', [{
256-
config,
257-
data,
258-
changedFields,
259-
cwd: cwd.get()
260-
}], context)
259+
plugins.callHook({
260+
id: 'configWrite',
261+
args: [{
262+
config,
263+
data,
264+
changedFields,
265+
cwd: cwd.get()
266+
}],
267+
file: cwd.get()
268+
}, context)
261269

262270
current = {}
263271
}

packages/@vue/cli-ui/apollo-server/connectors/plugins.js

Lines changed: 91 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const path = require('path')
22
const fs = require('fs')
33
const LRU = require('lru-cache')
4+
const chalk = require('chalk')
45
// Subs
56
const channels = require('../channels')
67
// Connectors
@@ -47,14 +48,13 @@ const logoCache = new LRU({
4748
// Local
4849
let currentPluginId
4950
let eventsInstalled = false
50-
let plugins = []
51-
let pluginApi
5251
let installationStep
53-
let projectId
52+
let pluginsStore = new Map()
53+
let pluginApiInstances = new Map()
5454

55-
function list (file, context, resetApi = true) {
55+
async function list (file, context, resetApi = true) {
5656
const pkg = folders.readPackage(file, context)
57-
plugins = []
57+
let plugins = []
5858
plugins = plugins.concat(findPlugins(pkg.devDependencies || {}))
5959
plugins = plugins.concat(findPlugins(pkg.dependencies || {}))
6060

@@ -66,11 +66,14 @@ function list (file, context, resetApi = true) {
6666
plugins.unshift(service)
6767
}
6868

69-
if (resetApi) resetPluginApi(context)
69+
pluginsStore.set(file, plugins)
70+
71+
if (resetApi || !pluginApiInstances.get(file)) await resetPluginApi({ file }, context)
7072
return plugins
7173
}
7274

73-
function findOne (id, context) {
75+
function findOne ({ id, file }, context) {
76+
const plugins = getPlugins(file)
7477
return plugins.find(
7578
p => p.id === id
7679
)
@@ -90,54 +93,77 @@ function findPlugins (deps) {
9093
)
9194
}
9295

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+
}
111101

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
130106

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))
134112
}
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+
}
136160

137-
return true
161+
resolve(true)
162+
})
163+
})
138164
}
139165

140-
function runPluginApi (id, context, fileName = 'ui') {
166+
function runPluginApi (id, pluginApi, context, fileName = 'ui') {
141167
let module
142168
try {
143169
module = loadModule(`${id}/${fileName}`, cwd.get(), true)
@@ -149,7 +175,7 @@ function runPluginApi (id, context, fileName = 'ui') {
149175
if (module) {
150176
pluginApi.pluginId = id
151177
module(pluginApi)
152-
log('Plugin API loaded for', id)
178+
log('Plugin API loaded for', id, chalk.grey(pluginApi.cwd))
153179
pluginApi.pluginId = null
154180
}
155181

@@ -160,7 +186,14 @@ function runPluginApi (id, context, fileName = 'ui') {
160186
} catch (e) {}
161187
}
162188

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)
164197
const fns = pluginApi.hooks[id]
165198
log(`Hook ${id}`, fns.length, 'handlers')
166199
fns.forEach(fn => fn(...args))
@@ -287,7 +320,7 @@ function runInvoke (id, context) {
287320
await invoke(id, prompts.getAnswers(), cwd.get())
288321
}
289322
// Run plugin api
290-
runPluginApi(id, context)
323+
runPluginApi(id, getApi(cwd.get()), context)
291324
installationStep = 'diff'
292325

293326
notify({
@@ -327,7 +360,7 @@ function update (id, context) {
327360
args: [id]
328361
})
329362
currentPluginId = id
330-
const plugin = findOne(id, context)
363+
const plugin = findOne({ id, file: cwd.get() }, context)
331364
const { current, wanted } = await dependencies.getVersion(plugin, context)
332365

333366
await updatePackage(cwd.get(), getCommand(cwd.get()), null, id)
@@ -343,11 +376,11 @@ function update (id, context) {
343376
icon: 'done'
344377
})
345378

346-
resetPluginApi(context)
379+
await resetPluginApi({ file: cwd.get() }, context)
347380
dependencies.invalidatePackage(id, context)
348381

349382
currentPluginId = null
350-
return findOne(id)
383+
return findOne({ id, file: cwd.get() }, context)
351384
})
352385
}
353386

@@ -387,17 +420,15 @@ async function updateAll (context) {
387420
icon: 'done'
388421
})
389422

390-
resetPluginApi(context)
423+
await resetPluginApi({ file: cwd.get() }, context)
391424

392425
return updatedPlugins
393426
})
394427
}
395428

396-
function getApi () {
397-
return pluginApi
398-
}
429+
async function callAction ({ id, params, file = cwd.get() }, context) {
430+
const pluginApi = getApi(file)
399431

400-
async function callAction ({ id, params }, context) {
401432
context.pubsub.publish(channels.PLUGIN_ACTION_CALLED, {
402433
pluginActionCalled: { id, params }
403434
})

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy