Skip to content

Commit 63ccde8

Browse files
author
Guillaume Chau
committed
feat(ui): install/uninstall plugin
1 parent da0d37e commit 63ccde8

19 files changed

+331
-35
lines changed

packages/@vue/cli-ui/src/components/InstantSearchInput.vue

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template>
22
<div class="instant-search-input">
33
<VueInput
4+
ref="input"
45
icon-left="search"
56
v-model="query"
67
class="big"
@@ -55,6 +56,10 @@ export default {
5556
}
5657
this.searchStore.start()
5758
this.searchStore.refresh()
59+
},
60+
61+
focus () {
62+
this.$refs.input.focus()
5863
}
5964
}
6065
}

packages/@vue/cli-ui/src/components/ItemLogo.vue

+17-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
:class="{
55
selected,
66
loaded,
7+
error,
78
vuejs: image && image.includes('vuejs')
89
}"
910
>
@@ -13,11 +14,12 @@
1314
icon="done"
1415
/>
1516
<img
16-
v-else-if="image"
17+
v-else-if="image && !error"
1718
class="image"
1819
:src="image"
1920
:key="image"
2021
@load="loaded = true"
22+
@error="error = true"
2123
>
2224
<VueIcon
2325
v-else
@@ -48,13 +50,20 @@ export default {
4850
4951
data () {
5052
return {
51-
loaded: false
53+
loaded: false,
54+
error: false
5255
}
5356
},
5457
5558
watch: {
56-
image (value) {
59+
image: 'reset',
60+
selected: 'reset'
61+
},
62+
63+
methods: {
64+
reset () {
5765
this.loaded = false
66+
this.error = false
5867
}
5968
}
6069
}
@@ -97,10 +106,14 @@ export default {
97106
animation zoom .1s
98107
transform none
99108
109+
&.selected,
110+
&.error
111+
.wrapper
112+
animation zoom .1s
113+
100114
&.selected
101115
.wrapper
102116
background $vue-color-primary
103-
animation zoom .1s
104117
.vue-icon
105118
>>> svg
106119
fill $vue-color-light

packages/@vue/cli-ui/src/components/PackageSearchItem.vue

+10
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
attribute-name="description"
3232
/>
3333
</span>
34+
<span v-if="official" class="info">
35+
<VueIcon icon="star" class="top medium"/>
36+
<span>Official</span>
37+
</span>
3438
<span class="info downloads">
3539
<VueIcon class="medium" icon="file_download"/>
3640
<span>{{ pkg.humanDownloadsLast30Days }}</span>
@@ -56,6 +60,12 @@ export default {
5660
type: Boolean,
5761
default: false
5862
}
63+
},
64+
65+
computed: {
66+
official () {
67+
return this.pkg.owner.name === 'vuejs'
68+
}
5969
}
6070
}
6171
</script>
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module.exports = {
22
CWD_CHANGED: 'cwd_changed',
33
PROGRESS_CHANGED: 'progress_changed',
4+
PROGRESS_REMOVED: 'progress_removed',
45
CONSOLE_LOG_ADDED: 'console_log_added'
56
}

packages/@vue/cli-ui/src/graphql-api/connectors/plugins.js

+93-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
const path = require('path')
22
const fs = require('fs')
33
const LRU = require('lru-cache')
4-
const { isPlugin, isOfficialPlugin, getPluginLink } = require('@vue/cli-shared-utils')
4+
const {
5+
isPlugin,
6+
isOfficialPlugin,
7+
getPluginLink,
8+
hasYarn
9+
} = require('@vue/cli-shared-utils')
510
const getPackageVersion = require('@vue/cli/lib/util/getPackageVersion')
11+
const {
12+
progress: installProgress,
13+
installPackage,
14+
uninstallPackage
15+
} = require('@vue/cli/lib/util/installDeps')
16+
const { loadOptions } = require('@vue/cli/lib/options')
617

718
const cwd = require('./cwd')
819
const folders = require('./folders')
20+
const prompts = require('./prompts')
21+
const progress = require('./progress')
922

1023
const metadataCache = new LRU({
1124
max: 200,
@@ -16,6 +29,11 @@ const logoCache = new LRU({
1629
max: 50
1730
})
1831

32+
const PROGRESS_ID = 'plugin-installation'
33+
34+
let currentPluginId
35+
let eventsInstalled = false
36+
1937
function getPath (id) {
2038
return path.join(cwd.get(), 'node_modules', id)
2139
}
@@ -108,9 +126,82 @@ async function getLogo ({ id }, context) {
108126
return null
109127
}
110128

129+
function getInstallation (context) {
130+
if (!eventsInstalled) {
131+
eventsInstalled = true
132+
133+
// Package installation progress events
134+
installProgress.on('progress', value => {
135+
if (progress.get(PROGRESS_ID)) {
136+
progress.set({ id: PROGRESS_ID, progress: value }, context)
137+
}
138+
})
139+
installProgress.on('log', message => {
140+
if (progress.get(PROGRESS_ID)) {
141+
progress.set({ id: PROGRESS_ID, info: message }, context)
142+
}
143+
})
144+
}
145+
146+
return {
147+
id: 'plugin-install',
148+
pluginId: currentPluginId,
149+
prompts: prompts.list()
150+
}
151+
}
152+
153+
function install (id, context) {
154+
return progress.wrap(PROGRESS_ID, context, async setProgress => {
155+
setProgress({
156+
status: 'plugin-install',
157+
args: [id]
158+
})
159+
160+
currentPluginId = id
161+
162+
const packageManager = loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
163+
await installPackage(cwd.get(), packageManager, null, id)
164+
165+
return getInstallation(context)
166+
})
167+
}
168+
169+
function uninstall (id, context) {
170+
return progress.wrap(PROGRESS_ID, context, async setProgress => {
171+
setProgress({
172+
status: 'plugin-uninstall',
173+
args: [id]
174+
})
175+
176+
currentPluginId = id
177+
178+
const packageManager = loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
179+
await uninstallPackage(cwd.get(), packageManager, null, id)
180+
181+
return getInstallation(context)
182+
})
183+
}
184+
185+
function invoke (id, context) {
186+
return progress.wrap(PROGRESS_ID, context, async setProgress => {
187+
setProgress({
188+
status: 'plugin-invoke',
189+
args: [id]
190+
})
191+
192+
currentPluginId = id
193+
// TODO
194+
return getInstallation(context)
195+
})
196+
}
197+
111198
module.exports = {
112199
list,
113200
getVersion,
114201
getDescription,
115-
getLogo
202+
getLogo,
203+
getInstallation,
204+
install,
205+
uninstall,
206+
invoke
116207
}

packages/@vue/cli-ui/src/graphql-api/connectors/progress.js

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ function set (data, context) {
1515
status: null,
1616
error: null,
1717
info: null,
18+
args: null,
1819
progress: -1
1920
}, progress))
2021
} else {
@@ -25,6 +26,7 @@ function set (data, context) {
2526
}
2627

2728
function remove (id, context) {
29+
context.pubsub.publish(channels.PROGRESS_REMOVED, { progressRemoved: { id } })
2830
return map.delete(id)
2931
}
3032

packages/@vue/cli-ui/src/graphql-api/resolvers.js

+14-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ module.exports = {
4242
foldersFavorite: (root, args, context) => folders.listFavorite(context),
4343
projects: (root, args, context) => projects.list(context),
4444
projectCurrent: (root, args, context) => projects.getCurrent(context),
45-
projectCreation: (root, args, context) => projects.getCreation(context)
45+
projectCreation: (root, args, context) => projects.getCreation(context),
46+
pluginInstallation: (root, args, context) => plugins.getInstallation(context)
4647
},
4748

4849
Mutation: {
@@ -60,7 +61,10 @@ module.exports = {
6061
projectImport: (root, { input }, context) => projects.import(input, context),
6162
projectOpen: (root, { id }, context) => projects.open(id, context),
6263
projectRemove: (root, { id }, context) => projects.remove(id, context),
63-
projectCwdReset: (root, args, context) => projects.resetCwd(context)
64+
projectCwdReset: (root, args, context) => projects.resetCwd(context),
65+
pluginInstall: (root, { id }, context) => plugins.install(id, context),
66+
pluginUninstall: (root, { id }, context) => plugins.uninstall(id, context),
67+
pluginInvoke: (root, { id }, context) => plugins.invoke(id, context)
6468
},
6569

6670
Subscription: {
@@ -75,6 +79,14 @@ module.exports = {
7579
(payload, variables) => payload.progressChanged.id === variables.id
7680
)
7781
},
82+
progressRemoved: {
83+
subscribe: withFilter(
84+
// Iterator
85+
(parent, args, { pubsub }) => pubsub.asyncIterator(channels.PROGRESS_REMOVED),
86+
// Filter
87+
(payload, variables) => payload.progressRemoved.id === variables.id
88+
)
89+
},
7890
consoleLogAdded: {
7991
subscribe: (parent, args, context) => {
8092
logs.init(context)

packages/@vue/cli-ui/src/graphql-api/type-defs.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,15 @@ type Plugin {
8484
website: String
8585
description: String
8686
githubStats: GitHubStats
87-
prompts: [Prompt]
8887
logo: String
8988
}
9089
90+
type PluginInstallation {
91+
id: ID!
92+
pluginId: ID
93+
prompts: [Prompt]
94+
}
95+
9196
type Feature {
9297
id: ID!
9398
name: String!
@@ -145,6 +150,7 @@ type Progress {
145150
error: String
146151
# Progress from 0 to 1 (-1 means disabled)
147152
progress: Float
153+
args: [String]
148154
}
149155
150156
type Query {
@@ -157,6 +163,7 @@ type Query {
157163
projects: [Project]
158164
projectCurrent: Project
159165
projectCreation: ProjectCreation
166+
pluginInstallation: PluginInstallation
160167
}
161168
162169
type Mutation {
@@ -172,12 +179,15 @@ type Mutation {
172179
projectCwdReset: String
173180
presetApply (id: ID!): ProjectCreation
174181
featureSetEnabled (id: ID!, enabled: Boolean): Feature
175-
pluginAdd (id: ID!): Plugin
176182
promptAnswer (input: PromptInput!): [Prompt]
183+
pluginInstall (id: ID!): PluginInstallation
184+
pluginUninstall (id: ID!): PluginInstallation
185+
pluginInvoke (id: ID!): PluginInstallation
177186
}
178187
179188
type Subscription {
180189
progressChanged (id: ID!): Progress
190+
progressRemoved (id: ID!): ID
181191
consoleLogAdded: ConsoleLog!
182192
cwdChanged: String!
183193
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import "./pluginInstallationFragment.gql"
2+
3+
mutation pluginInstall ($id: ID!) {
4+
pluginInstall (id: $id) {
5+
...pluginInstallation
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import "./pluginInstallationFragment.gql"
2+
3+
query pluginInstallation {
4+
pluginInstallation {
5+
...pluginInstallation
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#import "./promptFragment.gql"
2+
3+
fragment pluginInstallation on PluginInstallation {
4+
id
5+
prompts {
6+
...prompt
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import "./pluginInstallationFragment.gql"
2+
3+
mutation pluginInvoke ($id: ID!) {
4+
pluginInvoke (id: $id) {
5+
...pluginInstallation
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import "./pluginInstallationFragment.gql"
2+
3+
mutation pluginUninstall ($id: ID!) {
4+
pluginUninstall (id: $id) {
5+
...pluginInstallation
6+
}
7+
}

packages/@vue/cli-ui/src/graphql/progressFragment.gql

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ fragment progress on Progress {
44
info
55
error
66
progress
7+
args
78
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
subscription progressRemoved ($id: ID!) {
2+
progressRemoved (id: $id)
3+
}

0 commit comments

Comments
 (0)