Skip to content
This repository has been archived by the owner on Dec 6, 2021. It is now read-only.

Commit

Permalink
feat: support --plugin flag
Browse files Browse the repository at this point in the history
- support --plugin, --plugins flags
- better error handling for missing plugins
  • Loading branch information
egoist committed Dec 7, 2018
1 parent bd34439 commit 41dd692
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 62 deletions.
27 changes: 16 additions & 11 deletions core/poi/bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@
require('v8-compile-cache')
const Poi = require('..')

const poi = new Poi()

poi.run().catch(error => {
poi.spinner.stop()
if (error.poi) {
if (!error.dismiss) {
poi.logger.error(error.message)
async function main() {
try {
const poi = new Poi()
await poi.run()
} catch (error) {
require('../lib/utils/spinner').stop()
if (error.poi) {
if (!error.dismiss) {
require('@poi/logger').error(error.message)
}
} else {
console.error(error.stack)
}
} else {
console.error(error.stack)
process.exit(1)
}
process.exit(1)
})
}

main()
66 changes: 38 additions & 28 deletions core/poi/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const parseArgs = require('./utils/parseArgs')
const PoiError = require('./utils/PoiError')
const spinner = require('./utils/spinner')
const validateConfig = require('./utils/validateConfig')
const { normalizePlugins, mergePlugins } = require('./utils/plugins')

module.exports = class PoiCore {
constructor(
Expand All @@ -33,15 +34,15 @@ module.exports = class PoiCore {
this.spinner = spinner
this.PoiError = PoiError
// For plugins, it's only used in onCreateCLI hook
this.parsedArgs = parseArgs(args.slice(2))
this.parsedArgs = parseArgs(args)
this.hooks = new Hooks()
this.testRunners = new Map()

if (this.parsedArgs.has('debug')) {
logger.setOptions({ debug: true })
}

this.mode = this.parsedArgs.getValue('mode')
this.mode = this.parsedArgs.get('mode')
if (!this.mode) {
this.mode = 'development'
}
Expand All @@ -54,7 +55,7 @@ module.exports = class PoiCore {
this.mode = 'test'
}

this.cwd = this.parsedArgs.getValue('cwd')
this.cwd = this.parsedArgs.get('cwd')
if (!this.cwd) {
this.cwd = process.cwd()
}
Expand All @@ -81,7 +82,7 @@ module.exports = class PoiCore {
this.config = externalConfig
} else {
const configFiles = this.parsedArgs.has('config')
? [this.parsedArgs.getValue('config')]
? [this.parsedArgs.get('config')]
: defaultConfigFiles
const { path: configPath, data: config } = this.configLoader.load({
files: configFiles
Expand Down Expand Up @@ -132,6 +133,10 @@ module.exports = class PoiCore {
.option('--test', 'Alias for --mode test')
.option('--no-config', 'Disable config file')
.option('--config <path>', 'Set the path to config file')
.option(
'--plugin, --plugins <plugin>',
'Add a plugin (can be used for multiple times)'
)
.option('--debug', 'Show debug logs')
.option('--inspect-webpack', 'Inspect webpack config in your editor')
.version(require('../package').version)
Expand All @@ -150,33 +155,35 @@ module.exports = class PoiCore {
* @returns {void}
*/
applyPlugins() {
const cwd = this.resolveCwd()
const cliPlugins = normalizePlugins(
this.parsedArgs.get('plugin') || this.parsedArgs.get('plugins'),
cwd
)
const configPlugins = normalizePlugins(this.config.plugins, cwd)

this.plugins = [
require.resolve('./plugins/command-options'),
require.resolve('./plugins/config-babel'),
require.resolve('./plugins/config-vue'),
require.resolve('./plugins/config-css'),
require.resolve('./plugins/config-font'),
require.resolve('./plugins/config-image'),
require.resolve('./plugins/config-html'),
require.resolve('./plugins/config-electron'),
require.resolve('./plugins/config-misc-loaders'),
require.resolve('./plugins/watch'),
require.resolve('./plugins/serve'),
require.resolve('./plugins/eject-html')
{ resolve: require.resolve('./plugins/command-options') },
{ resolve: require.resolve('./plugins/config-babel') },
{ resolve: require.resolve('./plugins/config-vue') },
{ resolve: require.resolve('./plugins/config-css') },
{ resolve: require.resolve('./plugins/config-font') },
{ resolve: require.resolve('./plugins/config-image') },
{ resolve: require.resolve('./plugins/config-html') },
{ resolve: require.resolve('./plugins/config-electron') },
{ resolve: require.resolve('./plugins/config-misc-loaders') },
{ resolve: require.resolve('./plugins/watch') },
{ resolve: require.resolve('./plugins/serve') },
{ resolve: require.resolve('./plugins/eject-html') }
]
.concat(this.config.plugins || [])
.map(v => {
if (typeof v === 'string') {
v = { resolve: v }
.concat(mergePlugins(configPlugins, cliPlugins))
.map(plugin => {
if (typeof plugin.resolve === 'string') {
plugin._resolve = plugin.resolve
plugin.resolve = require(plugin.resolve)
}
if (typeof v.resolve === 'string') {
v = Object.assign({
resolve: require(resolveFrom(this.resolveCwd(), v.resolve))
})
}
return v
return plugin
})
.filter(Boolean)

// Run plugin's `filterPlugins` method
for (const plugin of this.plugins) {
Expand All @@ -191,7 +198,10 @@ module.exports = class PoiCore {
// Run plugin's `apply` method
for (const plugin of this.plugins) {
if (plugin.resolve.apply) {
logger.debug(`Using plugin: "${plugin.resolve.name}"`)
logger.debug(`Using plugin: \`${plugin.resolve.name}\``)
if (plugin._resolve) {
logger.debug(`location: ${plugin._resolve}`)
}
plugin.resolve.apply(this, plugin.resolve.options)
}
}
Expand Down
23 changes: 23 additions & 0 deletions core/poi/lib/utils/__test__/plugins.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const { mergePlugins } = require('../plugins')

test('merge', () => {
expect(
mergePlugins(
[{ resolve: 'foo' }, { resolve: 'bar', options: { foo: 'bar' } }],
[
{
resolve: 'foo'
},
{
resolve: 'baz'
}
]
)
).toEqual([
{ resolve: 'foo' },
{ resolve: 'bar', options: { foo: 'bar' } },
{
resolve: 'baz'
}
])
})
25 changes: 7 additions & 18 deletions core/poi/lib/utils/parseArgs.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
const cac = require('cac')

module.exports = _args => {
const args = _args.reduce((res, arg) => {
return res.concat(
arg.startsWith('-') && arg.includes('=') ? arg.split('=') : arg
)
}, [])
const cli = cac()
const { options } = cli.parse(_args)

return {
getValue(name) {
if (!this.has(name)) return

const index = args.indexOf(name.length === 1 ? `-${name}` : `--${name}`)
return args[index + 1]
get(name) {
return options[name]
},

has(name) {
if (name.length > 1) {
return args.includes(`--${name}`)
}

const RE = new RegExp(`^-([a-zA-Z]+)`)
return args.find(arg => {
return RE.test(arg) && RE.exec(arg)[1].includes(name)
})
return this.get(name) !== undefined
}
}
}
53 changes: 53 additions & 0 deletions core/poi/lib/utils/plugins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const resolveFrom = require('resolve-from')
const logger = require('@poi/logger')
const isLocalPath = require('./isLocalPath')
const PoiError = require('./PoiError')

const normalizePluginName = name => {
if (isLocalPath(name)) return name

// @poi/foo => @poi/plugin-foo
// @my-org/hehe => @my-org/poi-plugin-hehe
if (/^@[^/]+\//.test(name)) {
return name.replace(/^@([^/]+)\/(plugin-)?/, (_, m1) => {
return m1 === 'poi' ? `@poi/plugin-` : `@${m1}/poi-plugin-`
})
}

return name.replace(/^(poi-plugin-)?/, 'poi-plugin-')
}

exports.normalizePlugins = (plugins, cwd) => {
return [].concat(plugins || []).map(v => {
if (typeof v === 'string') {
v = { resolve: v }
}
if (typeof v.resolve === 'string') {
const pluginName = normalizePluginName(v.resolve)
const resolvedPlugin = resolveFrom.silent(cwd, pluginName)
if (!resolvedPlugin) {
const message = `Cannot find plugin \`${pluginName}\` in your project`
logger.error(message)
logger.error(`Did you forget to install it?`)
throw new PoiError({
message,
dismiss: true
})
}
v = Object.assign({}, v, {
resolve: resolvedPlugin
})
}
return v
})
}

exports.mergePlugins = (configPlugins, cliPlugins) => {
return configPlugins.concat(
cliPlugins.filter(cliPlugin => {
return !configPlugins.find(
configPlugin => configPlugin.resolve === cliPlugin.resolve
)
})
)
}
7 changes: 6 additions & 1 deletion core/poi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
"version": "12.0.0-beta.8",
"main": "lib/index.js",
"bin": "bin/cli.js",
"scripts": {
"test": "jest"
},
"files": [
"lib",
"bin",
"babel.js",
"webpack.config.js"
"webpack.config.js",
"!**/__test__/**"
],
"license": "MIT",
"dependencies": {
Expand Down Expand Up @@ -68,6 +72,7 @@
"xo": false,
"devDependencies": {
"@poi/test-utils": "^12.0.0-beta.0",
"jest": "^23.6.0",
"vue-template-compiler": "^2.5.17"
}
}
3 changes: 0 additions & 3 deletions jest.config.js

This file was deleted.

2 changes: 1 addition & 1 deletion tasks/test.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yarn lint && \
yarn jest && \
yarn lerna run test && \
cd test/kitchensink && \
yarn && \
yarn test

0 comments on commit 41dd692

Please sign in to comment.