From 75e86c64836925d28440f6c73e67ee64fc564f67 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Sat, 21 Apr 2018 16:52:23 +0200 Subject: [PATCH] fix(ui): prompts async methods + fixes --- packages/@vue/cli-plugin-eslint/ui.js | 31 ++++--- .../@vue/cli-shared-utils/lib/validate.js | 7 ++ .../src/components/ConfigurationItem.vue | 11 ++- .../cli-ui/src/graphql-api/api/PluginApi.js | 40 ++++++++- .../src/graphql-api/api/client-addon.js | 11 +++ .../src/graphql-api/api/configuration.js | 21 +++++ .../@vue/cli-ui/src/graphql-api/api/task.js | 22 +++++ .../graphql-api/connectors/configurations.js | 18 ++-- .../cli-ui/src/graphql-api/connectors/logs.js | 32 +++---- .../src/graphql-api/connectors/plugins.js | 4 +- .../src/graphql-api/connectors/projects.js | 34 ++++---- .../src/graphql-api/connectors/prompts.js | 84 ++++++++++--------- .../src/graphql-api/connectors/tasks.js | 18 ++-- .../src/graphql-api/schema/configuration.js | 2 +- .../cli-ui/src/graphql-api/schema/console.js | 5 +- 15 files changed, 229 insertions(+), 111 deletions(-) create mode 100644 packages/@vue/cli-ui/src/graphql-api/api/client-addon.js create mode 100644 packages/@vue/cli-ui/src/graphql-api/api/configuration.js create mode 100644 packages/@vue/cli-ui/src/graphql-api/api/task.js diff --git a/packages/@vue/cli-plugin-eslint/ui.js b/packages/@vue/cli-plugin-eslint/ui.js index 993ff10bb1..0027c5f21c 100644 --- a/packages/@vue/cli-plugin-eslint/ui.js +++ b/packages/@vue/cli-plugin-eslint/ui.js @@ -1,3 +1,5 @@ +/* eslint-disable vue-libs/no-async-functions */ + module.exports = api => { // Config file api.describeConfig({ @@ -46,7 +48,8 @@ module.exports = api => { link: 'https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/html-end-tags.md', default: false, value: data.rules && data.rules['vue/html-end-tags'] === 'error', - filter: input => JSON.stringify(input ? 'error' : 'off') + filter: input => JSON.stringify(input ? 'error' : 'off'), + transformer: input => input === JSON.stringify('error') }, { name: 'vue/html-indent', @@ -89,7 +92,8 @@ module.exports = api => { link: 'https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/html-self-closing.md', default: false, value: data.rules && data.rules['vue/html-self-closing'] === 'error', - filter: input => JSON.stringify(input ? 'error' : 'off') + filter: input => JSON.stringify(input ? 'error' : 'off'), + transformer: input => input === JSON.stringify('error') }, { name: 'vue/require-default-prop', @@ -100,7 +104,8 @@ module.exports = api => { link: 'https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/require-default-prop.md', default: false, value: data.rules && data.rules['vue/require-default-prop'] === 'error', - filter: input => JSON.stringify(input ? 'error' : 'off') + filter: input => JSON.stringify(input ? 'error' : 'off'), + transformer: input => input === JSON.stringify('error') }, { name: 'vue/require-prop-types', @@ -111,7 +116,8 @@ module.exports = api => { link: 'https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/require-prop-types.md', default: false, value: data.rules && data.rules['vue/require-prop-types'] === 'error', - filter: input => JSON.stringify(input ? 'error' : 'off') + filter: input => JSON.stringify(input ? 'error' : 'off'), + transformer: input => input === JSON.stringify('error') }, { name: 'vue/attributes-order', @@ -122,7 +128,8 @@ module.exports = api => { link: 'https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/attributes-order.md', default: false, value: data.rules && data.rules['vue/attributes-order'] === 'error', - filter: input => JSON.stringify(input ? 'error' : 'off') + filter: input => JSON.stringify(input ? 'error' : 'off'), + transformer: input => input === JSON.stringify('error') }, { name: 'vue/html-quotes', @@ -157,15 +164,17 @@ module.exports = api => { link: 'https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/order-in-components.md', default: false, value: data.rules && data.rules['vue/order-in-components'] === 'error', - filter: input => JSON.stringify(input ? 'error' : 'off') + filter: input => JSON.stringify(input ? 'error' : 'off'), + transformer: input => input === JSON.stringify('error') } ] }), - onWrite: ({ api, prompts }) => { - api.setData(prompts.reduce((obj, prompt) => { - obj[`rules.${prompt.id}`] = api.getAnswer(prompt.id, JSON.parse) - return obj - }, {})) + onWrite: async ({ api, prompts }) => { + const result = {} + for (const prompt of prompts) { + result[`rules.${prompt.id}`] = await api.getAnswer(prompt.id, JSON.parse) + } + api.setData(result) } }) diff --git a/packages/@vue/cli-shared-utils/lib/validate.js b/packages/@vue/cli-shared-utils/lib/validate.js index c1508a8411..90871c9bad 100644 --- a/packages/@vue/cli-shared-utils/lib/validate.js +++ b/packages/@vue/cli-shared-utils/lib/validate.js @@ -16,3 +16,10 @@ exports.validate = (obj, schema, cb) => { } }) } + +exports.validateSync = (obj, schema) => { + const result = joi.validate(obj, schema) + if (result.error) { + throw result.error + } +} diff --git a/packages/@vue/cli-ui/src/components/ConfigurationItem.vue b/packages/@vue/cli-ui/src/components/ConfigurationItem.vue index 54ddd75522..55efadac9e 100644 --- a/packages/@vue/cli-ui/src/components/ConfigurationItem.vue +++ b/packages/@vue/cli-ui/src/components/ConfigurationItem.vue @@ -37,9 +37,18 @@ export default { computed: { iconClass () { - return icons.getClassWithColor(this.configuration.icon || this.configuration.id) || 'gear-icon medium-blue' + return icons.getClassWithColor(this.getFileName(this.configuration.icon) || this.configuration.id) || 'gear-icon medium-blue' } }, + + methods: { + getFileName (icon) { + if (icon) { + if (!icon.includes('.')) return `f.${icon}` + return icon + } + } + } } diff --git a/packages/@vue/cli-ui/src/graphql-api/api/PluginApi.js b/packages/@vue/cli-ui/src/graphql-api/api/PluginApi.js index 716325e260..33c774a7dc 100644 --- a/packages/@vue/cli-ui/src/graphql-api/api/PluginApi.js +++ b/packages/@vue/cli-ui/src/graphql-api/api/PluginApi.js @@ -1,6 +1,10 @@ +const logs = require('../connectors/logs') const plugins = require('../connectors/plugins') const sharedData = require('../connectors/shared-data') const ipc = require('../utils/ipc') +const { validate: validateConfig } = require('./configuration') +const { validate: validateTask } = require('./task') +const { validate: validateClientAddon } = require('./client-addon') class PluginApi { constructor (context) { @@ -12,11 +16,31 @@ class PluginApi { } describeConfig (options) { - this.configurations.push(options) + try { + validateConfig(options) + this.configurations.push(options) + } catch (e) { + logs.add({ + type: 'error', + tag: 'PluginApi', + message: 'describeConfig options are invalid\n' + + e.message + }, this.context) + } } describeTask (options) { - this.tasks.push(options) + try { + validateTask(options) + this.tasks.push(options) + } catch (e) { + logs.add({ + type: 'error', + tag: 'PluginApi', + message: 'describeTask options are invalid\n' + + e.message + }, this.context) + } } getTask (command) { @@ -26,7 +50,17 @@ class PluginApi { } addClientAddon (options) { - this.clientAddons.push(options) + try { + validateClientAddon(options) + this.clientAddons.push(options) + } catch (e) { + logs.add({ + type: 'error', + tag: 'PluginApi', + message: 'addClientAddon options are invalid\n' + + e.message + }, this.context) + } } ipcOn (cb) { diff --git a/packages/@vue/cli-ui/src/graphql-api/api/client-addon.js b/packages/@vue/cli-ui/src/graphql-api/api/client-addon.js new file mode 100644 index 0000000000..93877d44ae --- /dev/null +++ b/packages/@vue/cli-ui/src/graphql-api/api/client-addon.js @@ -0,0 +1,11 @@ +const { createSchema, validateSync } = require('@vue/cli-shared-utils') + +const schema = createSchema(joi => ({ + id: joi.string().required(), + path: joi.string(), + url: joi.string() +})) + +exports.validate = (options) => { + validateSync(options, schema) +} diff --git a/packages/@vue/cli-ui/src/graphql-api/api/configuration.js b/packages/@vue/cli-ui/src/graphql-api/api/configuration.js new file mode 100644 index 0000000000..c3da7cf416 --- /dev/null +++ b/packages/@vue/cli-ui/src/graphql-api/api/configuration.js @@ -0,0 +1,21 @@ +const { createSchema, validateSync } = require('@vue/cli-shared-utils') + +const schema = createSchema(joi => ({ + id: joi.string().required(), + name: joi.string().required(), + description: joi.string(), + link: joi.string().uri(), + icon: joi.string(), + files: joi.object({ + json: joi.array().items(joi.string()), + js: joi.array().items(joi.string()), + yaml: joi.array().items(joi.string()), + package: joi.string() + }), + onRead: joi.func().required(), + onWrite: joi.func().required() +})) + +exports.validate = (options) => { + validateSync(options, schema) +} diff --git a/packages/@vue/cli-ui/src/graphql-api/api/task.js b/packages/@vue/cli-ui/src/graphql-api/api/task.js new file mode 100644 index 0000000000..63c2e36adb --- /dev/null +++ b/packages/@vue/cli-ui/src/graphql-api/api/task.js @@ -0,0 +1,22 @@ +const { createSchema, validateSync } = require('@vue/cli-shared-utils') + +const schema = createSchema(joi => ({ + match: joi.object().type(RegExp).required().description('Match a npm script command'), + description: joi.string(), + link: joi.string().uri(), + prompts: joi.array(), + views: joi.array().items(joi.object({ + id: joi.string().required(), + label: joi.string().required(), + icon: joi.string(), + component: joi.string().required() + })), + defaultView: joi.string(), + onBeforeRun: joi.func(), + onRun: joi.func(), + onExit: joi.func() +})) + +exports.validate = (options) => { + validateSync(options, schema) +} diff --git a/packages/@vue/cli-ui/src/graphql-api/connectors/configurations.js b/packages/@vue/cli-ui/src/graphql-api/connectors/configurations.js index 00017d3654..53487f6df6 100644 --- a/packages/@vue/cli-ui/src/graphql-api/connectors/configurations.js +++ b/packages/@vue/cli-ui/src/graphql-api/connectors/configurations.js @@ -92,7 +92,7 @@ function writeData ({ config, data }, context) { } } -function getPrompts (id, context) { +async function getPrompts (id, context) { const config = findOne(id, context) if (config) { const data = readData(config, context) @@ -100,27 +100,27 @@ function getPrompts (id, context) { config, data } - const configData = config.onRead({ + const configData = await config.onRead({ data }) - prompts.reset() + await prompts.reset() configData.prompts.forEach(prompts.add) if (configData.answers) { - prompts.setAnswers(configData.answers) + await prompts.setAnswers(configData.answers) } - prompts.start() + await prompts.start() return prompts.list() } return [] } -function save (id, context) { +async function save (id, context) { const config = findOne(id, context) if (config) { if (current.config === config) { const answers = prompts.getAnswers() let data = clone(current.data) - config.onWrite({ + await config.onWrite({ prompts: prompts.list(), answers, data, @@ -139,10 +139,10 @@ function save (id, context) { } }) }, - getAnswer: (id, mapper) => { + getAnswer: async (id, mapper) => { const prompt = prompts.findOne(id) if (prompt) { - const defaultValue = prompts.getDefaultValue(prompt) + const defaultValue = await prompts.getDefaultValue(prompt) if (defaultValue !== prompt.rawValue) { let value = get(answers, prompt.id) if (mapper) { diff --git a/packages/@vue/cli-ui/src/graphql-api/connectors/logs.js b/packages/@vue/cli-ui/src/graphql-api/connectors/logs.js index 6e4cf57ed7..5e51977a85 100644 --- a/packages/@vue/cli-ui/src/graphql-api/connectors/logs.js +++ b/packages/@vue/cli-ui/src/graphql-api/connectors/logs.js @@ -3,8 +3,9 @@ const { events } = require('@vue/cli-shared-utils/lib/logger') const { generateTitle } = require('@vue/cli/lib/util/clearConsole') // Subs const channels = require('../channels') +// Context +const getContext = require('../context') -let init = false let logs = [] exports.add = function (log, context) { @@ -21,21 +22,6 @@ exports.add = function (log, context) { return item } -exports.init = function (context) { - if (!init) { - init = true - events.on('log', log => { - exports.add(log, context) - }) - - exports.add({ - type: 'info', - tag: null, - message: generateTitle(true) - }, context) - } -} - exports.list = function (context) { return logs } @@ -51,3 +37,17 @@ exports.clear = function (context) { logs = [] return logs } + +// Init +{ + const context = getContext(null) + events.on('log', log => { + exports.add(log, context) + }) + + exports.add({ + type: 'info', + tag: null, + message: generateTitle(true) + }, context) +} diff --git a/packages/@vue/cli-ui/src/graphql-api/connectors/plugins.js b/packages/@vue/cli-ui/src/graphql-api/connectors/plugins.js index 2777c45339..5c601542b1 100644 --- a/packages/@vue/cli-ui/src/graphql-api/connectors/plugins.js +++ b/packages/@vue/cli-ui/src/graphql-api/connectors/plugins.js @@ -272,7 +272,7 @@ function finishInstall (context) { } async function initPrompts (id, context) { - prompts.reset() + await prompts.reset() try { let data = require(path.join(getPath(id), 'prompts.js')) if (typeof data === 'function') { @@ -282,7 +282,7 @@ async function initPrompts (id, context) { } catch (e) { console.warn(`No prompts found for ${id}`) } - prompts.start() + await prompts.start() } function update (id, context) { diff --git a/packages/@vue/cli-ui/src/graphql-api/connectors/projects.js b/packages/@vue/cli-ui/src/graphql-api/connectors/projects.js index a6621d0953..cbd21dd166 100644 --- a/packages/@vue/cli-ui/src/graphql-api/connectors/projects.js +++ b/packages/@vue/cli-ui/src/graphql-api/connectors/projects.js @@ -51,7 +51,7 @@ function generateProjectCreation (creator) { } } -function initCreator (context) { +async function initCreator (context) { const creator = new Creator('', cwd.get(), getPromptModules()) /* Event listeners */ @@ -128,10 +128,10 @@ function initCreator (context) { ] // Prompts - prompts.reset() + await prompts.reset() creator.injectedPrompts.forEach(prompts.add) - updatePromptsFeatures() - prompts.start() + await updatePromptsFeatures() + await prompts.start() return creator } @@ -145,15 +145,15 @@ function removeCreator (context) { } } -function getCreation (context) { +async function getCreation (context) { if (!creator) { - creator = initCreator(context) + creator = await initCreator(context) } return generateProjectCreation(creator) } -function updatePromptsFeatures () { - prompts.changeAnswers(answers => { +async function updatePromptsFeatures () { + await prompts.changeAnswers(answers => { answers.features = features.filter( f => f.enabled ).map( @@ -162,18 +162,18 @@ function updatePromptsFeatures () { }) } -function setFeatureEnabled ({ id, enabled, updatePrompts = true }, context) { +async function setFeatureEnabled ({ id, enabled, updatePrompts = true }, context) { const feature = features.find(f => f.id === id) if (feature) { feature.enabled = enabled } else { console.warn(`Feature '${id}' not found`) } - if (updatePrompts) updatePromptsFeatures() + if (updatePrompts) await updatePromptsFeatures() return feature } -function applyPreset (id, context) { +async function applyPreset (id, context) { const preset = presets.find(p => p.id === id) if (preset) { for (const feature of features) { @@ -184,19 +184,19 @@ function applyPreset (id, context) { } if (preset.raw) { if (preset.raw.router) { - setFeatureEnabled({ id: 'router', enabled: true, updatePrompts: false }, context) + await setFeatureEnabled({ id: 'router', enabled: true, updatePrompts: false }, context) } if (preset.raw.vuex) { - setFeatureEnabled({ id: 'vuex', enabled: true, updatePrompts: false }, context) + await setFeatureEnabled({ id: 'vuex', enabled: true, updatePrompts: false }, context) } if (preset.raw.cssPreprocessor) { - setFeatureEnabled({ id: 'css-preprocessor', enabled: true, updatePrompts: false }, context) + await setFeatureEnabled({ id: 'css-preprocessor', enabled: true, updatePrompts: false }, context) } if (preset.raw.useConfigFiles) { - setFeatureEnabled({ id: 'use-config-files', enabled: true, updatePrompts: false }, context) + await setFeatureEnabled({ id: 'use-config-files', enabled: true, updatePrompts: false }, context) } } - updatePromptsFeatures() + await updatePromptsFeatures() } else { console.warn(`Preset '${id}' not found`) } @@ -234,7 +234,7 @@ async function create (input, context) { // Answers const answers = prompts.getAnswers() - prompts.reset() + await prompts.reset() let index // Package Manager diff --git a/packages/@vue/cli-ui/src/graphql-api/connectors/prompts.js b/packages/@vue/cli-ui/src/graphql-api/connectors/prompts.js index 9dd5175cc2..136ec1ac29 100644 --- a/packages/@vue/cli-ui/src/graphql-api/connectors/prompts.js +++ b/packages/@vue/cli-ui/src/graphql-api/connectors/prompts.js @@ -15,10 +15,11 @@ function generatePromptError (value) { } } -function getEnabled (value) { +async function getEnabled (value) { const type = typeof value if (type === 'function') { - return !!value(answers) + const result = await value(answers) + return !!result } else if (type === 'boolean') { return value } else { @@ -34,7 +35,7 @@ function validateInput (prompt, value) { return true } -function getValue (prompt, value) { +function getFilteredValue (prompt, value) { const filter = prompt.raw.filter if (typeof filter === 'function') { return filter(value) @@ -42,17 +43,17 @@ function getValue (prompt, value) { return value } -function getDisplayedValue (prompt, value) { +function getTransformedValue (prompt, value) { const transformer = prompt.raw.transformer if (typeof transformer === 'function') { - value = transformer(value, answers) + return transformer(value, answers) } - return JSON.stringify(value) + return value } function generatePromptChoice (prompt, data, defaultValue) { return { - value: getDisplayedValue(prompt, data.value), + value: getTransformedValue(prompt, data.value), name: data.name, checked: data.checked, disabled: data.disabled, @@ -60,7 +61,7 @@ function generatePromptChoice (prompt, data, defaultValue) { } } -function getChoices (prompt) { +async function getChoices (prompt) { const data = prompt.raw.choices if (!data) { return null @@ -68,13 +69,14 @@ function getChoices (prompt) { let result if (typeof data === 'function') { - result = data(answers) + result = await data(answers) } else { result = data } - const defaultValue = prompt.type === 'list' || prompt.type === 'rawlist' - ? getDefaultValue(prompt) - : undefined + let defaultValue + if (prompt.type === 'list' || prompt.type === 'rawlist') { + defaultValue = await getDefaultValue(prompt) + } return result.map( item => generatePromptChoice(prompt, item, defaultValue) ) @@ -107,26 +109,30 @@ function generatePrompt (data) { } } -function updatePrompts () { +async function updatePrompts () { for (const prompt of prompts) { const oldVisible = prompt.visible - prompt.visible = getEnabled(prompt.raw.when) + prompt.visible = await getEnabled(prompt.raw.when) - prompt.choices = getChoices(prompt) + prompt.choices = await getChoices(prompt) if (oldVisible !== prompt.visible && !prompt.visible) { removeAnswer(prompt.id) prompt.valueChanged = false } else if (prompt.visible && !prompt.valueChanged) { let value - if (typeof prompt.raw.value !== 'undefined') { + let answer = getAnswer(prompt.id) + if (typeof answer !== 'undefined') { + value = await getTransformedValue(prompt, answer) + } else if (typeof prompt.raw.value !== 'undefined') { value = prompt.raw.value } else { value = getDefaultValue(prompt) } prompt.rawValue = value - prompt.value = getDisplayedValue(prompt, value) - setAnswer(prompt.id, getValue(prompt, value)) + prompt.value = JSON.stringify(value) + const finalValue = await getFilteredValue(prompt, value) + setAnswer(prompt.id, finalValue) } } @@ -135,14 +141,14 @@ function updatePrompts () { // Public API -function setAnswers (newAnswers) { +async function setAnswers (newAnswers) { answers = newAnswers - updatePrompts() + await updatePrompts() } -function changeAnswers (cb) { +async function changeAnswers (cb) { cb(answers) - updatePrompts() + await updatePrompts() } function getAnswers () { @@ -153,9 +159,9 @@ function getAnswer (id) { return ObjectUtil.get(answers, id) } -function reset () { +async function reset () { prompts = [] - setAnswers({}) + await setAnswers({}) } function list () { @@ -166,8 +172,8 @@ function add (data) { prompts.push(generatePrompt(data)) } -function start () { - updatePrompts() +async function start () { + await updatePrompts() } function remove (id) { @@ -175,25 +181,25 @@ function remove (id) { index !== -1 && prompts.splice(index, 1) } -function setValue ({ id, value }) { +async function setValue ({ id, value }) { const prompt = findOne(id) if (!prompt) { console.warn(`Prompt '${prompt}' not found`) return null } - const validation = validateInput(prompt, value) + const validation = await validateInput(prompt, value) if (validation !== true) { prompt.error = generatePromptError(validation) } else { prompt.error = null } - const finalValue = getValue(prompt, value) prompt.rawValue = value - prompt.value = getDisplayedValue(prompt, value) + const finalValue = await getFilteredValue(prompt, value) + prompt.value = JSON.stringify(value) prompt.valueChanged = true setAnswer(prompt.id, finalValue) - updatePrompts() + await updatePrompts() return prompt } @@ -203,12 +209,14 @@ function findOne (id) { ) } -function getDefaultValue (prompt) { - const defaultValue = prompt.raw.default +async function getDefaultValue (prompt) { + let defaultValue = prompt.raw.default if (typeof defaultValue === 'function') { - return defaultValue(answers) - } else if (prompt.type === 'checkbox') { - const choices = getChoices(prompt) + defaultValue = await defaultValue(answers) + } + + if (prompt.type === 'checkbox') { + const choices = await getChoices(prompt) if (choices) { return choices.filter( c => c.checked @@ -222,8 +230,8 @@ function getDefaultValue (prompt) { return defaultValue } -function answerPrompt ({ id, value }, context) { - setValue({ id, value: JSON.parse(value) }) +async function answerPrompt ({ id, value }, context) { + await setValue({ id, value: JSON.parse(value) }) return list() } diff --git a/packages/@vue/cli-ui/src/graphql-api/connectors/tasks.js b/packages/@vue/cli-ui/src/graphql-api/connectors/tasks.js index dede705829..fedce7e58f 100644 --- a/packages/@vue/cli-ui/src/graphql-api/connectors/tasks.js +++ b/packages/@vue/cli-ui/src/graphql-api/connectors/tasks.js @@ -119,16 +119,16 @@ function updateSavedData (data, context) { } } -function getPrompts (id, context) { +async function getPrompts (id, context) { const task = findOne(id, context) if (task) { - prompts.reset() + await prompts.reset() task.prompts.forEach(prompts.add) const data = getSavedData(id, context) if (data) { - prompts.setAnswers(data.answers) + await prompts.setAnswers(data.answers) } - prompts.start() + await prompts.start() return prompts.list() } } @@ -200,7 +200,7 @@ function updateRouteBadges ({ task, data }, context) { } } -function run (id, context) { +async function run (id, context) { const task = findOne(id, context) if (task && task.status !== 'running') { const args = ['run', task.name] @@ -215,7 +215,7 @@ function run (id, context) { // Plugin API if (task.onBeforeRun) { - task.onBeforeRun({ + await task.onBeforeRun({ answers, args }) @@ -232,7 +232,7 @@ function run (id, context) { // Plugin API if (task.onRun) { - task.onRun({ + await task.onRun({ args, child, cwd: cwd.get() @@ -265,10 +265,10 @@ function run (id, context) { }, context) }) - const onExit = (code, signal) => { + const onExit = async (code, signal) => { // Plugin API if (task.onExit) { - task.onExit({ + await task.onExit({ args, child, cwd: cwd.get(), diff --git a/packages/@vue/cli-ui/src/graphql-api/schema/configuration.js b/packages/@vue/cli-ui/src/graphql-api/schema/configuration.js index 6e7aebb603..9e9c1e67eb 100644 --- a/packages/@vue/cli-ui/src/graphql-api/schema/configuration.js +++ b/packages/@vue/cli-ui/src/graphql-api/schema/configuration.js @@ -15,7 +15,7 @@ extend type Mutation { type Configuration implements DescribedEntity { id: ID! - name: String + name: String! description: String link: String icon: String diff --git a/packages/@vue/cli-ui/src/graphql-api/schema/console.js b/packages/@vue/cli-ui/src/graphql-api/schema/console.js index 5044315136..e078d31bb5 100644 --- a/packages/@vue/cli-ui/src/graphql-api/schema/console.js +++ b/packages/@vue/cli-ui/src/graphql-api/schema/console.js @@ -47,10 +47,7 @@ exports.resolvers = { Subscription: { consoleLogAdded: { - subscribe: (parent, args, context) => { - logs.init(context) - return context.pubsub.asyncIterator(channels.CONSOLE_LOG_ADDED) - } + subscribe: (parent, args, context) => context.pubsub.asyncIterator(channels.CONSOLE_LOG_ADDED) } } }