feat: local service plugins, closes #1841

This commit is contained in:
Guillaume Chau
2018-07-13 17:39:07 +02:00
parent d212dcd63e
commit 08352811e0
14 changed files with 58 additions and 20 deletions
+16
View File
@@ -75,6 +75,22 @@ For example, if you have a `.config/package.json` file:
```
:::
### Project local plugin
If you need access to the plugin API in your project and don't want to create a full plugin for it, you can use the `vuePlugins.service` option in your `package.json` file:
```json
{
"vuePlugins": {
"service": ["my-commands.js"]
}
}
```
Each file will need to export a function taking the plugin API as the first argument. For more information about the plugin API, check out the [Plugin Development Guide](../dev-guide/plugin-dev.md).
You can also create a `vue-cli-ui.js` file that will behave like a UI plugin. For more information, read the [UI Plugin API](../dev-guide/ui-api.md).
## Presets
A Vue CLI preset is a JSON object that contains pre-defined options and plugins for creating a new project so that the user don't have to go through the prompts to select them.
+24 -4
View File
@@ -8,7 +8,7 @@ const Config = require('webpack-chain')
const PluginAPI = require('./PluginAPI')
const loadEnv = require('./util/loadEnv')
const defaultsDeep = require('lodash.defaultsdeep')
const { warn, error, isPlugin } = require('@vue/cli-shared-utils')
const { warn, error, isPlugin, loadModule } = require('@vue/cli-shared-utils')
const { defaults, validate } = require('./options')
@@ -22,6 +22,9 @@ module.exports = class Service {
this.webpackRawConfigFns = []
this.devServerConfigFns = []
this.commands = {}
// Folder containing the target package.json for plugins
this.pkgContext = context
// package.json containing the plugins
this.pkg = this.resolvePkg(pkg)
// If there are inline plugins, they will be used instead of those
// found in package.json.
@@ -42,7 +45,8 @@ module.exports = class Service {
} else if (fs.existsSync(path.join(context, 'package.json'))) {
const pkg = readPkg.sync({ cwd: context })
if (pkg.vuePlugins && pkg.vuePlugins.resolveFrom) {
return this.resolvePkg(null, path.resolve(context, pkg.vuePlugins.resolveFrom))
this.pkgContext = path.resolve(context, pkg.vuePlugins.resolveFrom)
return this.resolvePkg(null, this.pkgContext)
}
return pkg
} else {
@@ -132,6 +136,8 @@ module.exports = class Service {
apply: require(id)
})
let plugins
const builtInPlugins = [
'./commands/serve',
'./commands/build',
@@ -146,7 +152,7 @@ module.exports = class Service {
].map(idToPlugin)
if (inlinePlugins) {
return useBuiltIn !== false
plugins = useBuiltIn !== false
? builtInPlugins.concat(inlinePlugins)
: inlinePlugins
} else {
@@ -154,8 +160,22 @@ module.exports = class Service {
.concat(Object.keys(this.pkg.dependencies || {}))
.filter(isPlugin)
.map(idToPlugin)
return builtInPlugins.concat(projectPlugins)
plugins = builtInPlugins.concat(projectPlugins)
}
// Local plugins
if (this.pkg.vuePlugins && this.pkg.vuePlugins.service) {
const files = this.pkg.vuePlugins.service
if (!Array.isArray(files)) {
throw new Error(`Invalid type for option 'vuePlugins.service', expected 'array' but got ${typeof files}.`)
}
plugins = plugins.concat(files.map(file => ({
id: `local:${file}`,
apply: loadModule(file, this.pkgContext)
})))
}
return plugins
}
async run (name, args = {}, rawArgv = []) {
+1
View File
@@ -3,6 +3,7 @@
'exit',
'ipc',
'logger',
'module',
'object',
'openBrowser',
'pluginResolution',
@@ -27,6 +27,7 @@
"ora": "^2.1.0",
"request": "^2.87.0",
"request-promise-native": "^1.0.5",
"semver": "^5.5.0",
"string.prototype.padstart": "^3.0.0"
},
"publishConfig": {
@@ -9,9 +9,8 @@ const plugins = require('./plugins')
const folders = require('./folders')
const prompts = require('./prompts')
// Utils
const { get, set, unset } = require('@vue/cli-shared-utils')
const { get, set, unset, loadModule } = require('@vue/cli-shared-utils')
const { log } = require('../util/logger')
const { loadModule } = require('@vue/cli/lib/util/module')
const extendJSConfig = require('@vue/cli/lib/util/extendJSConfig')
const fileTypes = ['js', 'json', 'yaml']
@@ -11,8 +11,7 @@ const logs = require('./logs')
// Context
const getContext = require('../context')
// Utils
const { isPlugin, hasYarn } = require('@vue/cli-shared-utils')
const { resolveModule } = require('@vue/cli/lib/util/module')
const { isPlugin, hasYarn, resolveModule } = require('@vue/cli-shared-utils')
const getPackageVersion = require('@vue/cli/lib/util/getPackageVersion')
const {
progress: installProgress,
@@ -24,9 +24,11 @@ const PluginApi = require('../api/PluginApi')
const {
isPlugin,
isOfficialPlugin,
getPluginLink
getPluginLink,
resolveModule,
loadModule,
clearModule
} = require('@vue/cli-shared-utils')
const { resolveModule, loadModule, clearModule } = require('@vue/cli/lib/util/module')
const {
progress: installProgress,
installPackage,
@@ -5,9 +5,8 @@ const Creator = require('@vue/cli/lib/Creator')
const { getPromptModules } = require('@vue/cli/lib/util/createTools')
const { getFeatures } = require('@vue/cli/lib/util/features')
const { defaults } = require('@vue/cli/lib/options')
const { toShortPluginId } = require('@vue/cli-shared-utils')
const { toShortPluginId, clearModule } = require('@vue/cli-shared-utils')
const { progress: installProgress } = require('@vue/cli/lib/util/installDeps')
const { clearModule } = require('@vue/cli/lib/util/module')
const parseGitConfig = require('parse-git-config')
// Connectors
const progress = require('./progress')
@@ -1,4 +1,4 @@
const { loadModule } = require('@vue/cli/lib/util/module')
const { loadModule } = require('@vue/cli-shared-utils')
const invoke = require('@vue/cli/lib/invoke')
const ROUTER = 'org.vue.vue-router-add'
+2 -2
View File
@@ -7,7 +7,6 @@ const inquirer = require('inquirer')
const Generator = require('./Generator')
const cloneDeep = require('lodash.clonedeep')
const sortObject = require('./util/sortObject')
const { loadModule } = require('./util/module')
const getVersions = require('./util/getVersions')
const { installDeps } = require('./util/installDeps')
const { clearConsole } = require('./util/clearConsole')
@@ -34,7 +33,8 @@ const {
hasYarn,
logWithSpinner,
stopSpinner,
exit
exit,
loadModule
} = require('@vue/cli-shared-utils')
const isManualMode = answers => answers.preset === '__manual__'
+3 -2
View File
@@ -2,13 +2,14 @@ const chalk = require('chalk')
const invoke = require('./invoke')
const { loadOptions } = require('./options')
const { installPackage } = require('./util/installDeps')
const { resolveModule, loadModule } = require('./util/module')
const {
log,
error,
hasProjectYarn,
stopSpinner,
resolvePluginId
resolvePluginId,
resolveModule,
loadModule
} = require('@vue/cli-shared-utils')
async function add (pluginName, options = {}, context = process.cwd()) {
+2 -2
View File
@@ -7,7 +7,6 @@ const inquirer = require('inquirer')
const isBinary = require('isbinaryfile')
const Generator = require('./Generator')
const { loadOptions } = require('./options')
const { loadModule } = require('./util/module')
const { installDeps } = require('./util/installDeps')
const normalizeFilePaths = require('./util/normalizeFilePaths')
const {
@@ -17,7 +16,8 @@ const {
hasProjectGit,
logWithSpinner,
stopSpinner,
resolvePluginId
resolvePluginId,
loadModule
} = require('@vue/cli-shared-utils')
async function readFiles (context) {
@@ -1,6 +1,6 @@
const extendJSConfig = require('./extendJSConfig')
const stringifyJS = require('./stringifyJS')
const { loadModule } = require('./module')
const { loadModule } = require('@vue/cli-shared-utils')
const merge = require('deepmerge')
const isObject = val => val && typeof val === 'object'