You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
5.8 KiB
217 lines
5.8 KiB
const path = require('path') |
|
const hash = require('hash-sum') |
|
const { semver, matchesPluginId } = require('@vue/cli-shared-utils') |
|
|
|
// Note: if a plugin-registered command needs to run in a specific default mode, |
|
// the plugin needs to expose it via `module.exports.defaultModes` in the form |
|
// of { [commandName]: mode }. This is because the command mode needs to be |
|
// known and applied before loading user options / applying plugins. |
|
|
|
class PluginAPI { |
|
/** |
|
* @param {string} id - Id of the plugin. |
|
* @param {Service} service - A vue-cli-service instance. |
|
*/ |
|
constructor (id, service) { |
|
this.id = id |
|
this.service = service |
|
} |
|
|
|
get version () { |
|
return require('../package.json').version |
|
} |
|
|
|
assertVersion (range) { |
|
if (typeof range === 'number') { |
|
if (!Number.isInteger(range)) { |
|
throw new Error('Expected string or integer value.') |
|
} |
|
range = `^${range}.0.0-0` |
|
} |
|
if (typeof range !== 'string') { |
|
throw new Error('Expected string or integer value.') |
|
} |
|
|
|
if (semver.satisfies(this.version, range, { includePrerelease: true })) return |
|
|
|
throw new Error( |
|
`Require @vue/cli-service "${range}", but was loaded with "${this.version}".` |
|
) |
|
} |
|
|
|
/** |
|
* Current working directory. |
|
*/ |
|
getCwd () { |
|
return this.service.context |
|
} |
|
|
|
/** |
|
* Resolve path for a project. |
|
* |
|
* @param {string} _path - Relative path from project root |
|
* @return {string} The resolved absolute path. |
|
*/ |
|
resolve (_path) { |
|
return path.resolve(this.service.context, _path) |
|
} |
|
|
|
/** |
|
* Check if the project has a given plugin. |
|
* |
|
* @param {string} id - Plugin id, can omit the (@vue/|vue-|@scope/vue)-cli-plugin- prefix |
|
* @return {boolean} |
|
*/ |
|
hasPlugin (id) { |
|
return this.service.plugins.some(p => matchesPluginId(id, p.id)) |
|
} |
|
|
|
/** |
|
* Register a command that will become available as `vue-cli-service [name]`. |
|
* |
|
* @param {string} name |
|
* @param {object} [opts] |
|
* { |
|
* description: string, |
|
* usage: string, |
|
* options: { [string]: string } |
|
* } |
|
* @param {function} fn |
|
* (args: { [string]: string }, rawArgs: string[]) => ?Promise |
|
*/ |
|
registerCommand (name, opts, fn) { |
|
if (typeof opts === 'function') { |
|
fn = opts |
|
opts = null |
|
} |
|
this.service.commands[name] = { fn, opts: opts || {} } |
|
} |
|
|
|
/** |
|
* Register a function that will receive a chainable webpack config |
|
* the function is lazy and won't be called until `resolveWebpackConfig` is |
|
* called |
|
* |
|
* @param {function} fn |
|
*/ |
|
chainWebpack (fn) { |
|
this.service.webpackChainFns.push(fn) |
|
} |
|
|
|
/** |
|
* Register |
|
* - a webpack configuration object that will be merged into the config |
|
* OR |
|
* - a function that will receive the raw webpack config. |
|
* the function can either mutate the config directly or return an object |
|
* that will be merged into the config. |
|
* |
|
* @param {object | function} fn |
|
*/ |
|
configureWebpack (fn) { |
|
this.service.webpackRawConfigFns.push(fn) |
|
} |
|
|
|
/** |
|
* Register a dev serve config function. It will receive the express `app` |
|
* instance of the dev server. |
|
* |
|
* @param {function} fn |
|
*/ |
|
configureDevServer (fn) { |
|
this.service.devServerConfigFns.push(fn) |
|
} |
|
|
|
/** |
|
* Resolve the final raw webpack config, that will be passed to webpack. |
|
* |
|
* @param {ChainableWebpackConfig} [chainableConfig] |
|
* @return {object} Raw webpack config. |
|
*/ |
|
resolveWebpackConfig (chainableConfig) { |
|
return this.service.resolveWebpackConfig(chainableConfig) |
|
} |
|
|
|
/** |
|
* Resolve an intermediate chainable webpack config instance, which can be |
|
* further tweaked before generating the final raw webpack config. |
|
* You can call this multiple times to generate different branches of the |
|
* base webpack config. |
|
* See https://github.com/mozilla-neutrino/webpack-chain |
|
* |
|
* @return {ChainableWebpackConfig} |
|
*/ |
|
resolveChainableWebpackConfig () { |
|
return this.service.resolveChainableWebpackConfig() |
|
} |
|
|
|
/** |
|
* Generate a cache identifier from a number of variables |
|
*/ |
|
genCacheConfig (id, partialIdentifier, configFiles = []) { |
|
const fs = require('fs') |
|
const cacheDirectory = this.resolve(`node_modules/.cache/${id}`) |
|
|
|
// replace \r\n to \n generate consistent hash |
|
const fmtFunc = conf => { |
|
if (typeof conf === 'function') { |
|
return conf.toString().replace(/\r\n?/g, '\n') |
|
} |
|
return conf |
|
} |
|
|
|
const variables = { |
|
partialIdentifier, |
|
'cli-service': require('../package.json').version, |
|
env: process.env.NODE_ENV, |
|
test: !!process.env.VUE_CLI_TEST, |
|
config: [ |
|
fmtFunc(this.service.projectOptions.chainWebpack), |
|
fmtFunc(this.service.projectOptions.configureWebpack) |
|
] |
|
} |
|
|
|
try { |
|
variables['cache-loader'] = require('cache-loader/package.json').version |
|
} catch (e) { |
|
// cache-loader is only intended to be used for webpack 4 |
|
} |
|
|
|
if (!Array.isArray(configFiles)) { |
|
configFiles = [configFiles] |
|
} |
|
configFiles = configFiles.concat([ |
|
'package-lock.json', |
|
'yarn.lock', |
|
'pnpm-lock.yaml' |
|
]) |
|
|
|
const readConfig = file => { |
|
const absolutePath = this.resolve(file) |
|
if (!fs.existsSync(absolutePath)) { |
|
return |
|
} |
|
|
|
if (absolutePath.endsWith('.js')) { |
|
// should evaluate config scripts to reflect environment variable changes |
|
try { |
|
return JSON.stringify(require(absolutePath)) |
|
} catch (e) { |
|
return fs.readFileSync(absolutePath, 'utf-8') |
|
} |
|
} else { |
|
return fs.readFileSync(absolutePath, 'utf-8') |
|
} |
|
} |
|
|
|
variables.configFiles = configFiles.map(file => { |
|
const content = readConfig(file) |
|
return content && content.replace(/\r\n?/g, '\n') |
|
}) |
|
|
|
const cacheIdentifier = hash(variables) |
|
return { cacheDirectory, cacheIdentifier } |
|
} |
|
} |
|
|
|
module.exports = PluginAPI
|
|
|