From c853f444bcffb99c87fdcb75dd7ce06578393418 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Fri, 5 Jun 2020 09:22:26 +0530 Subject: [PATCH] feat(webpack-cli): allow multiple entry flags --- packages/webpack-cli/README.md | 2 +- .../webpack-cli/__tests__/arg-parser.test.js | 19 ++++++++++++++- packages/webpack-cli/lib/groups/BasicGroup.js | 4 ++++ packages/webpack-cli/lib/utils/arg-parser.js | 5 +++- packages/webpack-cli/lib/utils/cli-flags.js | 3 ++- test/entry/flag-entry/entry-with-flag.test.js | 24 ++++++++++++++++--- test/entry/flag-entry/src/b.js | 1 + 7 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 test/entry/flag-entry/src/b.js diff --git a/packages/webpack-cli/README.md b/packages/webpack-cli/README.md index 7b7a8b42e7e..23a0e50da12 100644 --- a/packages/webpack-cli/README.md +++ b/packages/webpack-cli/README.md @@ -35,7 +35,7 @@ Available Commands Options - --entry string The entry point of your application. + --entry string[] The entry point(s) of your application. -c, --config string Provide path to a webpack configuration file -m, --merge string Merge a configuration file using webpack-merge --progress Print compilation progress during build diff --git a/packages/webpack-cli/__tests__/arg-parser.test.js b/packages/webpack-cli/__tests__/arg-parser.test.js index ab7600321d0..d3b4dd55246 100644 --- a/packages/webpack-cli/__tests__/arg-parser.test.js +++ b/packages/webpack-cli/__tests__/arg-parser.test.js @@ -38,6 +38,13 @@ const basicOptions = [ }, description: 'custom type flag', }, + { + name: 'multiple-flag', + usage: '--multiple-flag ', + type: String, + multiple: true, + description: 'multiple flag', + }, ]; const helpAndVersionOptions = basicOptions.slice(0); @@ -176,6 +183,16 @@ describe('arg-parser', () => { expect(warnMock.mock.calls.length).toEqual(0); }); + it('handles multiple same args', () => { + const res = argParser(basicOptions, ['--multiple-flag', 'a.js', '--multiple-flag', 'b.js'], true); + expect(res.unknownArgs.length).toEqual(0); + expect(res.opts).toEqual({ + multipleFlag: ['a.js', 'b.js'], + stringFlagWithDefault: 'default-value', + }); + expect(warnMock.mock.calls.length).toEqual(0); + }); + it('calls help callback on --help', () => { const helpCb = jest.fn(); argParser(helpAndVersionOptions, ['--help'], true, '', helpCb); @@ -192,7 +209,7 @@ describe('arg-parser', () => { it('parses webpack args', () => { const res = argParser(core, ['--entry', 'test.js', '--hot', '-o', './dist/', '--no-watch'], true); expect(res.unknownArgs.length).toEqual(0); - expect(res.opts.entry).toEqual('test.js'); + expect(res.opts.entry).toEqual(['test.js']); expect(res.opts.hot).toBeTruthy(); expect(res.opts.output).toEqual('./dist/'); expect(res.opts.watch).toBeFalsy(); diff --git a/packages/webpack-cli/lib/groups/BasicGroup.js b/packages/webpack-cli/lib/groups/BasicGroup.js index 723ad85c455..1db7d5c4ee9 100644 --- a/packages/webpack-cli/lib/groups/BasicGroup.js +++ b/packages/webpack-cli/lib/groups/BasicGroup.js @@ -1,4 +1,5 @@ const GroupHelper = require('../utils/GroupHelper'); +const chalk = require('chalk'); const { core, groups } = require('../utils/cli-flags'); class BasicGroup extends GroupHelper { @@ -35,6 +36,9 @@ class BasicGroup extends GroupHelper { } if (arg === 'entry') { options[arg] = this.resolveFilePath(args[arg], 'index.js'); + if (options[arg].length === 0) { + process.stdout.write(chalk.red('\nError: you provided an invalid entry point.\n')); + } } }); if (outputOptions['dev']) { diff --git a/packages/webpack-cli/lib/utils/arg-parser.js b/packages/webpack-cli/lib/utils/arg-parser.js index 6bdfc51f502..0e92fa1c8a1 100644 --- a/packages/webpack-cli/lib/utils/arg-parser.js +++ b/packages/webpack-cli/lib/utils/arg-parser.js @@ -38,13 +38,16 @@ function argParser(options, args, argsOnly = false, name = '', helpFunction = un options.reduce((parserInstance, option) => { const flags = option.alias ? `-${option.alias}, --${option.name}` : `--${option.name}`; const flagsWithType = option.type !== Boolean ? flags + ' ' : flags; - if (option.type === Boolean || option.type === String) { + if ((option.type === Boolean || option.type === String) && !option.multiple) { parserInstance.option(flagsWithType, option.description, option.defaultValue); if (option.type === Boolean) { // commander requires explicitly adding the negated version of boolean flags const negatedFlag = `--no-${option.name}`; parserInstance.option(negatedFlag, `negates ${option.name}`); } + } else if (option.multiple) { + const multiArg = (value, previous = []) => previous.concat([value]); + parserInstance.option(flagsWithType, option.description, multiArg, option.defaultValue); } else { // in this case the type is a parsing function parserInstance.option(flagsWithType, option.description, option.type, option.defaultValue); diff --git a/packages/webpack-cli/lib/utils/cli-flags.js b/packages/webpack-cli/lib/utils/cli-flags.js index b18df20a84d..0d79219354a 100644 --- a/packages/webpack-cli/lib/utils/cli-flags.js +++ b/packages/webpack-cli/lib/utils/cli-flags.js @@ -74,9 +74,10 @@ module.exports = { name: 'entry', usage: '--entry ', type: String, + multiple: true, defaultOption: true, group: BASIC_GROUP, - description: 'The entry point of your application e.g. ./src/main.js', + description: 'The entry point(s) of your application e.g. ./src/main.js', link: 'https://webpack.js.org/concepts/#entry', }, { diff --git a/test/entry/flag-entry/entry-with-flag.test.js b/test/entry/flag-entry/entry-with-flag.test.js index 1c579907131..e368b42d4d9 100644 --- a/test/entry/flag-entry/entry-with-flag.test.js +++ b/test/entry/flag-entry/entry-with-flag.test.js @@ -39,9 +39,27 @@ describe('entry flag', () => { }); }); - it('should throw error for invalid entry file', () => { - const { stderr, stdout } = run(__dirname, ['--entry', './src/test.js']); + it('should load multiple entries provided by user', (done) => { + const { stderr, stdout } = run(__dirname, ['--entry', 'src/a.js', '--entry', 'src/b.js']); expect(stderr).toBeFalsy(); - expect(stdout).toContain('not found'); + expect(stdout).toBeTruthy(); + + stat(resolve(__dirname, './bin/main.js'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + done(); + }); + readFile(resolve(__dirname, './bin/main.js'), 'utf-8', (err, data) => { + expect(err).toBe(null); + expect(data).toContain('Hello from a.js'); + expect(data).toContain('Hello from b.js'); + done(); + }); + }); + + it('should throw error for invalid entry file', () => { + const { stderr, stdout } = run(__dirname, ['--entry', 'as']); + expect(stderr).toBeTruthy(); + expect(stdout).toContain('you provided an invalid entry point'); }); }); diff --git a/test/entry/flag-entry/src/b.js b/test/entry/flag-entry/src/b.js new file mode 100644 index 00000000000..4eb2d45c855 --- /dev/null +++ b/test/entry/flag-entry/src/b.js @@ -0,0 +1 @@ +console.log('Hello from b.js');