Skip to content

Commit

Permalink
feat(webpack-cli): allow multiple entry flags
Browse files Browse the repository at this point in the history
  • Loading branch information
snitin315 committed Jun 5, 2020
1 parent 0e912c1 commit c853f44
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 7 deletions.
2 changes: 1 addition & 1 deletion packages/webpack-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 18 additions & 1 deletion packages/webpack-cli/__tests__/arg-parser.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ const basicOptions = [
},
description: 'custom type flag',
},
{
name: 'multiple-flag',
usage: '--multiple-flag <value>',
type: String,
multiple: true,
description: 'multiple flag',
},
];

const helpAndVersionOptions = basicOptions.slice(0);
Expand Down Expand Up @@ -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);
Expand All @@ -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();
Expand Down
4 changes: 4 additions & 0 deletions packages/webpack-cli/lib/groups/BasicGroup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const GroupHelper = require('../utils/GroupHelper');
const chalk = require('chalk');
const { core, groups } = require('../utils/cli-flags');

class BasicGroup extends GroupHelper {
Expand Down Expand Up @@ -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']) {
Expand Down
5 changes: 4 additions & 1 deletion packages/webpack-cli/lib/utils/arg-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 + ' <value>' : 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);
Expand Down
3 changes: 2 additions & 1 deletion packages/webpack-cli/lib/utils/cli-flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ module.exports = {
name: 'entry',
usage: '--entry <path to entry file>',
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',
},
{
Expand Down
24 changes: 21 additions & 3 deletions test/entry/flag-entry/entry-with-flag.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});
});
1 change: 1 addition & 0 deletions test/entry/flag-entry/src/b.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('Hello from b.js');

0 comments on commit c853f44

Please sign in to comment.