Skip to content

Commit 0a6891a

Browse files
author
Guillaume Chau
committed
feat(ui): task run (wip stop not working)
1 parent 8e3198d commit 0a6891a

File tree

15 files changed

+316
-28
lines changed

15 files changed

+316
-28
lines changed

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
</template>
2121

2222
<script>
23+
import { isSameRoute, isIncludedRoute } from '../util/route'
24+
2325
const BUILTIN_ROUTES = [
2426
{
2527
name: 'project-plugins',
@@ -52,14 +54,14 @@ export default {
5254
computed: {
5355
currentRoute: {
5456
get () {
55-
const currentRoute = this.$route.name
57+
const currentRoute = this.$route
5658
const route = this.routes.find(
57-
r => currentRoute.indexOf(r.name) === 0
59+
item => isIncludedRoute(currentRoute, this.$router.resolve({ name: item.name }).route)
5860
)
59-
return route ? route.name : null
61+
return route && route.name
6062
},
6163
set (name) {
62-
if (this.$route.name !== name) {
64+
if (!isSameRoute(this.$route, this.$router.resolve({ name }).route)) {
6365
this.$router.push({ name })
6466
}
6567
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@ module.exports = {
22
CWD_CHANGED: 'cwd_changed',
33
PROGRESS_CHANGED: 'progress_changed',
44
PROGRESS_REMOVED: 'progress_removed',
5-
CONSOLE_LOG_ADDED: 'console_log_added'
5+
CONSOLE_LOG_ADDED: 'console_log_added',
6+
TASK_CHANGED: 'task_changed',
7+
TASK_LOG_ADDED: 'task_log_added'
68
}

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

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ const semver = require('semver')
55
const {
66
isPlugin,
77
isOfficialPlugin,
8-
getPluginLink,
9-
hasYarn
8+
getPluginLink
109
} = require('@vue/cli-shared-utils')
1110
const getPackageVersion = require('@vue/cli/lib/util/getPackageVersion')
1211
const {
@@ -15,7 +14,6 @@ const {
1514
uninstallPackage,
1615
updatePackage
1716
} = require('@vue/cli/lib/util/installDeps')
18-
const { loadOptions } = require('@vue/cli/lib/options')
1917
const invoke = require('@vue/cli/lib/invoke')
2018

2119
const cwd = require('./cwd')
@@ -24,6 +22,8 @@ const prompts = require('./prompts')
2422
const progress = require('./progress')
2523
const logs = require('./logs')
2624

25+
const { getCommand } = require('../utils/command')
26+
2727
const metadataCache = new LRU({
2828
max: 200,
2929
maxAge: 1000 * 60 * 30
@@ -178,8 +178,7 @@ function install (id, context) {
178178

179179
currentPluginId = id
180180

181-
const packageManager = loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
182-
await installPackage(cwd.get(), packageManager, null, id)
181+
await installPackage(cwd.get(), getCommand(), null, id)
183182

184183
await initPrompts(id, context)
185184

@@ -196,8 +195,7 @@ function uninstall (id, context) {
196195

197196
currentPluginId = id
198197

199-
const packageManager = loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
200-
await uninstallPackage(cwd.get(), packageManager, null, id)
198+
await uninstallPackage(cwd.get(), getCommand(), null, id)
201199

202200
currentPluginId = null
203201

@@ -248,8 +246,7 @@ function update (id, context) {
248246
const plugin = findOne(id, context)
249247
const { current, wanted } = await getVersion(plugin, context)
250248

251-
const packageManager = loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
252-
await updatePackage(cwd.get(), packageManager, null, id)
249+
await updatePackage(cwd.get(), getCommand(), null, id)
253250

254251
logs.add({
255252
message: `Plugin ${id} updated from ${current} to ${wanted}`,
Lines changed: 155 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,176 @@
1+
const execa = require('execa')
2+
3+
const channels = require('../channels')
14
const cwd = require('./cwd')
25
const folders = require('./folders')
6+
const logs = require('./logs')
7+
8+
const { getCommand } = require('../utils/command')
39

4-
let tasks = []
10+
const tasks = new Map()
11+
12+
function getTasks () {
13+
const file = cwd.get()
14+
let list = tasks.get(file)
15+
if (!list) {
16+
list = []
17+
tasks.set(file, list)
18+
}
19+
return list
20+
}
521

622
function list (context) {
23+
let list = getTasks()
724
const file = cwd.get()
825
const pkg = folders.readPackage(file, context)
9-
tasks = []
1026
if (pkg.scripts) {
11-
tasks = Object.keys(pkg.scripts).map(
12-
name => ({
13-
id: `${file}:${name}`,
14-
name,
15-
command: pkg.scripts[name],
16-
status: 'idle'
27+
const existing = new Map()
28+
29+
// Get current valid tasks in project `package.json`
30+
const currentTasks = Object.keys(pkg.scripts).map(
31+
name => {
32+
const id = `${file}:${name}`
33+
existing.set(id, true)
34+
return {
35+
id,
36+
name,
37+
command: pkg.scripts[name],
38+
index: list.findIndex(t => t.id === id)
39+
}
40+
}
41+
)
42+
43+
// Process existing tasks
44+
const existingTasks = currentTasks.filter(
45+
task => task.index !== -1
46+
)
47+
// Update tasks data
48+
existingTasks.forEach(task => {
49+
Object.assign(list[task.index], task)
50+
})
51+
52+
// Process new tasks
53+
const newTasks = currentTasks.filter(
54+
task => task.index === -1
55+
).map(
56+
task => ({
57+
...task,
58+
status: 'idle',
59+
child: null,
60+
logs: []
1761
})
1862
)
63+
64+
// Keep existing or ran tasks
65+
list = list.filter(
66+
task => existing.get(task.id) ||
67+
task.status !== 'idle'
68+
)
69+
70+
// Add the new tasks
71+
list = list.concat(newTasks)
72+
73+
tasks.set(file, list)
1974
}
20-
return tasks
75+
return list
2176
}
2277

2378
function findOne (id, context) {
24-
return tasks.find(
79+
return getTasks().find(
2580
t => t.id === id
2681
)
2782
}
2883

84+
function updateOne (data, context) {
85+
const task = findOne(data.id)
86+
if (task) {
87+
Object.assign(task, data)
88+
context.pubsub.publish(channels.TASK_CHANGED, {
89+
taskChanged: task
90+
})
91+
}
92+
return task
93+
}
94+
95+
function run (id, context) {
96+
const task = findOne(id, context)
97+
if (task && task.status !== 'running') {
98+
const args = ['run', task.name]
99+
100+
const child = execa(getCommand(), args, {
101+
cwd: cwd.get(),
102+
stdio: ['inherit', 'pipe', 'pipe']
103+
})
104+
105+
updateOne({
106+
id: task.id,
107+
status: 'running',
108+
child
109+
}, context)
110+
logs.add({
111+
message: `Task ${task.id} started`,
112+
type: 'info'
113+
}, context)
114+
115+
child.stdout.on('data', buffer => {
116+
// TODO logs
117+
console.log(buffer.toString())
118+
})
119+
120+
child.stderr.on('data', buffer => {
121+
// TODO logs
122+
console.log(buffer.toString())
123+
})
124+
125+
child.on('close', (code, signal) => {
126+
if (signal === 'SIGINT') {
127+
updateOne({
128+
id: task.id,
129+
status: 'error',
130+
child: null
131+
}, context)
132+
logs.add({
133+
message: `Task ${task.id} was terminated`,
134+
type: 'error'
135+
}, context)
136+
} else if (code !== 0) {
137+
updateOne({
138+
id: task.id,
139+
status: 'error',
140+
child: null
141+
}, context)
142+
logs.add({
143+
message: `Task ${task.id} ended with error code`,
144+
type: 'error'
145+
}, context)
146+
} else {
147+
updateOne({
148+
id: task.id,
149+
status: 'done',
150+
child: null
151+
}, context)
152+
logs.add({
153+
message: `Task ${task.id} completed`,
154+
type: 'done'
155+
}, context)
156+
}
157+
})
158+
}
159+
return task
160+
}
161+
162+
function stop (id, context) {
163+
const task = findOne(id, context)
164+
if (task && task.status === 'running') {
165+
task.child.kill('SIGINT') // TODO not working
166+
}
167+
return task
168+
}
169+
29170
module.exports = {
30171
list,
31-
findOne
172+
findOne,
173+
run,
174+
stop,
175+
updateOne
32176
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ module.exports = {
7070
pluginInstall: (root, { id }, context) => plugins.install(id, context),
7171
pluginUninstall: (root, { id }, context) => plugins.uninstall(id, context),
7272
pluginInvoke: (root, { id }, context) => plugins.runInvoke(id, context),
73-
pluginUpdate: (root, { id }, context) => plugins.update(id, context)
73+
pluginUpdate: (root, { id }, context) => plugins.update(id, context),
74+
taskRun: (root, { id }, context) => tasks.run(id, context),
75+
taskStop: (root, { id }, context) => tasks.stop(id, context)
7476
},
7577

7678
Subscription: {
@@ -98,6 +100,9 @@ module.exports = {
98100
logs.init(context)
99101
return context.pubsub.asyncIterator(channels.CONSOLE_LOG_ADDED)
100102
}
103+
},
104+
taskChanged: {
105+
subscribe: (parent, args, { pubsub }) => pubsub.asyncIterator(channels.TASK_CHANGED)
101106
}
102107
}
103108
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,15 @@ type Mutation {
203203
pluginUninstall (id: ID!): PluginInstallation
204204
pluginInvoke (id: ID!): PluginInstallation
205205
pluginUpdate (id: ID!): Plugin
206+
taskRun (id: ID!): Task
207+
taskStop (id: ID!): Task
206208
}
207209
208210
type Subscription {
209211
progressChanged (id: ID!): Progress
210212
progressRemoved (id: ID!): ID
211213
consoleLogAdded: ConsoleLog!
212214
cwdChanged: String!
215+
taskChanged: Task
213216
}
214217
`
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const {
2+
hasYarn
3+
} = require('@vue/cli-shared-utils')
4+
const { loadOptions } = require('@vue/cli/lib/options')
5+
6+
exports.getCommand = function () {
7+
return loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import "./taskFragment.gql"
2+
3+
subscription taskChanged {
4+
taskChanged {
5+
...task
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import "./taskFragment.gql"
2+
3+
mutation taskRun ($id: ID!) {
4+
taskRun (id: $id) {
5+
...task
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import "./taskFragment.gql"
2+
3+
mutation taskStop ($id: ID!) {
4+
taskStop (id: $id) {
5+
...task
6+
}
7+
}

packages/@vue/cli-ui/src/locales/en.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,13 @@
234234
},
235235
"project-tasks": {
236236
"title": "Project tasks"
237+
},
238+
"project-task-details": {
239+
"actions": {
240+
"play": "Run task",
241+
"stop": "Stop task"
242+
},
243+
"command": "Script command"
237244
}
238245
}
239246
}

packages/@vue/cli-ui/src/locales/fr.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
},
7171
"log": {
7272
"tooltip": "Journal<br><i>Cliquer pour Afficher/Masquer le Journal Vue CLI</i>",
73-
"empty": "Aucun entrée dans le journal"
73+
"empty": "Aucune entrée dans le journal"
7474
}
7575
}
7676
},
@@ -234,6 +234,13 @@
234234
},
235235
"project-tasks": {
236236
"title": "Tâches du projet"
237+
},
238+
"project-task-details": {
239+
"actions": {
240+
"play": "Lancer la tâche",
241+
"stop": "Arrêter la tâche"
242+
},
243+
"command": "Commande de script"
237244
}
238245
}
239246
}

packages/@vue/cli-ui/src/views/ProjectConfiguration.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<div class="project-configuration page">
33
<ContentView
44
:title="$t('views.project-configuration.title')"
5+
class="limit-width"
56
>
67
WIP
78
</ContentView>

0 commit comments

Comments
 (0)