diff --git a/lib/API.js b/lib/API.js index efe26c5d..bd23fa41 100644 --- a/lib/API.js +++ b/lib/API.js @@ -5,11 +5,18 @@ const defaultsDeep = require('lodash/defaultsDeep'); class API { constructor(context, mode = 'development', verbose = false) { + this.plugins = []; + this.commands = []; this.context = context; this.mode = mode; this.verbose = verbose; this.logger = initLogger(); this.projectOptions = defaultsDeep(loadUserOptions(), defaults()); + this.resolvePlugins(); + } + + registerCommand(commandName, opts, fn) { + this.commands[commandName] = { opts, fn }; } executeCommand(commandName, params) { @@ -17,14 +24,31 @@ class API { throw new Error('You must specify a command to run.'); } - const command = require(resolve(__dirname, 'commands', commandName)); + const command = this.commands[commandName]; + if (!command) { + throw new Error(`Command "${commandName}" does not exist.`); + } return new Promise((resolve, reject) => { - return command(...params) + return command.fn(params) .then(() => resolve()) .catch(err => reject(err)); }); } + + /** + * @private + */ + resolvePlugins() { + this.plugins = [ + './commands/build', + './commands/lint', + ]; + + this.plugins.forEach(plugin => { + require(plugin)(this); + }); + } } module.exports = API; diff --git a/lib/Cli.js b/lib/Cli.js index 8311d386..26379103 100644 --- a/lib/Cli.js +++ b/lib/Cli.js @@ -19,7 +19,7 @@ class Cli { this.init(args.mode, args.v); return new Promise((resolve, reject) => { - return this.api.executeCommand(commandName, [this.api, args]) + return this.api.executeCommand(commandName, args) .then(() => resolve()) .catch(err => reject(err)); }); diff --git a/lib/commands/build/index.js b/lib/commands/build/index.js index 963d9f03..5282f7b0 100644 --- a/lib/commands/build/index.js +++ b/lib/commands/build/index.js @@ -2,16 +2,26 @@ const { readAssets } = require('../../utils/assets'); const handle = require('./handle'); const watch = require('./watch'); -module.exports = build = (api, args) => { - return new Promise(() => { - const assets = readAssets(api, args); +module.exports = api => { + api.registerCommand('build', { + description: 'build files', + usage: 'yprox-cli build [options]', + options: { + ...require('../commonOptions'), + '--watch': 'enable watch mode', + '--lint': 'lint before build, if lint fails, files will not be build', + }, + }, args => { + return new Promise(() => { + const assets = readAssets(api, args); - assets.forEach(entry => { - if (args.watch && entry.handler !== 'rollup') { // we gonna use rollup own watcher - watch(api, entry, args)(handle); - } else { - handle(api, entry, args); - } + assets.forEach(entry => { + if (args.watch && entry.handler !== 'rollup') { // we gonna use rollup own watcher + watch(api, entry, args)(handle); + } else { + handle(api, entry, args); + } + }); }); }); }; diff --git a/lib/commands/commonOptions.js b/lib/commands/commonOptions.js new file mode 100644 index 00000000..26b4797a --- /dev/null +++ b/lib/commands/commonOptions.js @@ -0,0 +1,5 @@ +module.exports = { + '--help': 'display help', + '--mode': 'specify env mode (default: development)', + '--filter: ': 'apply a filter on file entries', +}; diff --git a/lib/commands/lint/index.js b/lib/commands/lint/index.js index d4e4668d..2e29a692 100644 --- a/lib/commands/lint/index.js +++ b/lib/commands/lint/index.js @@ -3,31 +3,40 @@ const { chain } = require('lodash'); const { readAssets } = require('../../utils/assets'); const linters = require('./linters'); -module.exports = lint = (api, args) => { - return new Promise((resolve, reject) => { - const files = chain(readAssets(api, args)) - .filter(({ handler }) => Object.keys(linters).includes(handler)) - .map(normalizeEntrySrc) - .groupBy('handler') - .value(); - - Object.entries(files).forEach(([linter, entries]) => { - if (!(linter in linters)) { - return; - } - - const filesToLint = chain(entries) - .map(entry => entry.src) - .flatten() +module.exports = api => { + api.registerCommand('lint', { + description: 'lint files', + usage: 'yprox-cli lint [options]', + options: { + ...require('../commonOptions'), + '--fix': 'automatically fix lint errors', + }, + }, args => { + return new Promise((resolve, reject) => { + const files = chain(readAssets(api, args)) + .filter(({ handler }) => Object.keys(linters).includes(handler)) + .map(normalizeEntrySrc) + .groupBy('handler') .value(); - if (filesToLint.length === 0) { - return; - } + Object.entries(files).forEach(([linter, entries]) => { + if (!(linter in linters)) { + return; + } - return linters[linter]()(api, args, filesToLint) - .then(() => resolve()) - .catch(err => reject(err)); + const filesToLint = chain(entries) + .map(entry => entry.src) + .flatten() + .value(); + + if (filesToLint.length === 0) { + return; + } + + return linters[linter]()(api, args, filesToLint) + .then(() => resolve()) + .catch(err => reject(err)); + }); }); }); };