Skip to content

Commit

Permalink
Allow only valid options for commands (#1467)
Browse files Browse the repository at this point in the history
* error on invalid options

* adding test

* adding changeset

* fixing tests

* bug fix

* fixing tests
  • Loading branch information
prateekbh authored Nov 12, 2020
1 parent 4cc93ba commit 67fafc8
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 76 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-drinks-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'preact-cli': patch
---

Allow only valid options for commands.
83 changes: 82 additions & 1 deletion packages/cli/lib/commands/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ const { resolve } = require('path');
const { promisify } = require('util');
const { isDir, error } = require('../util');
const runWebpack = require('../lib/webpack/run-webpack');
const { validateArgs } = require('./validate-args');

const toBool = val => val === void 0 || (val === 'false' ? false : val);

module.exports = async function (src, argv) {
async function command(src, argv) {
validateArgs(argv, options, 'build');
argv.src = src || argv.src;
// add `default:true`s, `--no-*` disables
argv.prerender = toBool(argv.prerender);
Expand All @@ -32,4 +34,83 @@ module.exports = async function (src, argv) {
if (argv.json) {
await runWebpack.writeJsonStats(stats);
}
}

const options = [
{
name: '--src',
description: 'Specify source directory',
default: 'src',
},
{
name: '--dest',
description: 'Specify output directory',
default: 'build',
},
{
name: '--cwd',
description: 'A directory to use instead of $PWD',
default: '.',
},
{
name: '--esm',
description: 'Builds ES-2015 bundles for your code',
default: true,
},
{
name: '--sw',
description: 'Generate and attach a Service Worker',
default: true,
},
{
name: '--babelConfig',
description: 'Path to custom Babel config',
default: '.babelrc',
},
{
name: '--json',
description: 'Generate build stats for bundle analysis',
},
{
name: '--template',
description: 'Path to custom HTML template',
},
{
name: '--preload',
description: 'Adds preload tags to the document its assets',
default: false,
},
{
name: '--analyze',
description: 'Launch interactive Analyzer to inspect production bundle(s)',
},
{
name: '--prerenderUrls',
description: 'Path to pre-rendered routes config',
default: 'prerender-urls.json',
},
{
name: '--brotli',
description: 'Builds brotli compressed bundles of javascript',
default: false,
},
{
name: '--inline-css',
description: 'Adds critical css to the prerendered markup',
default: true,
},
{
name: '-c, --config',
description: 'Path to custom CLI config',
default: 'preact.config.js',
},
{
name: '-v, --verbose',
description: 'Verbose output',
},
];

module.exports = {
command,
options,
};
51 changes: 50 additions & 1 deletion packages/cli/lib/commands/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const {
FALLBACK_TEMPLATE_OPTIONS,
} = require('../constants');
const { addScripts, install, initGit } = require('../lib/setup');
const { validateArgs } = require('./validate-args');

const ORG = 'preactjs-templates';
const RGX = /\.(woff2?|ttf|eot|jpe?g|ico|png|gif|webp|mp4|mov|ogg|webm)(\?.*)?$/i;
Expand Down Expand Up @@ -163,7 +164,8 @@ async function copyFileToDestination(srcPath, destPath, force = false) {
}
}

module.exports = async function (repo, dest, argv) {
async function command(repo, dest, argv) {
validateArgs(argv, options, 'create');
// Prompt if incomplete data
if (!repo || !dest) {
const templates = await fetchTemplates();
Expand Down Expand Up @@ -381,4 +383,51 @@ module.exports = async function (repo, dest, argv) {
${green(pfx + ' serve')}
`) + '\n'
);
}

const options = [
{
name: '--name',
description: 'The application name',
},
{
name: '--cwd',
description: 'A directory to use instead of $PWD',
default: '.',
},
{
name: '--force',
description: 'Force destination output; will override!',
default: false,
},
{
name: '--install',
description: 'Install dependencies',
default: true,
},
{
name: '--yarn',
description: 'Use `yarn` instead of `npm`',
default: false,
},
{
name: '--git',
description: 'Initialize git repository',
default: false,
},
{
name: '--license',
description: 'License type',
default: 'MIT',
},
{
name: '-v, --verbose',
description: 'Verbose output',
default: false,
},
];

module.exports = {
command,
options,
};
18 changes: 14 additions & 4 deletions packages/cli/lib/commands/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
exports.build = require('./build');
exports.create = require('./create');
exports.list = require('./list');
exports.watch = require('./watch');
const { command: build, options: buildOptions } = require('./build');
const { command: create, options: createOptions } = require('./create');
const list = require('./list');
const { command: watch, options: watchOptions } = require('./watch');

module.exports = {
build,
buildOptions,
create,
createOptions,
list,
watch,
watchOptions,
};
29 changes: 29 additions & 0 deletions packages/cli/lib/commands/validate-args.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const { error } = require('../util');

function validateArgs(argv, options, command) {
let normalizedOptions = options.map(option => option.name.split(',')).flat(1);
normalizedOptions = normalizedOptions.map(option => {
option = option.trim();
if (option.startsWith('--')) {
return option.substr(2);
} else if (option.startsWith('-')) {
return option.substr(1);
}
});
for (const arg in argv) {
if (arg === '_') {
// ignore this arg
continue;
}
if (!normalizedOptions.includes(arg)) {
error(
`Invalid argument ${arg} passed to ${command}. Please refer to 'preact ${command} --help' for full list of options.\n\n`
);
throw new Error('Invalid argunment found.');
}
}
}

module.exports = {
validateArgs,
};
100 changes: 99 additions & 1 deletion packages/cli/lib/commands/watch.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const runWebpack = require('../lib/webpack/run-webpack');
const { warn } = require('../util');
const { validateArgs } = require('./validate-args');

module.exports = async function (src, argv) {
async function command(src, argv) {
validateArgs(argv, options, 'watch');
if (argv.rhl) {
delete argv.rhl;
argv.refresh = argv.rhl;
Expand All @@ -19,4 +21,100 @@ module.exports = async function (src, argv) {
}

return runWebpack(argv, true);
}

const options = [
{
name: '--src',
description: 'Specify source directory',
default: 'src',
},
{
name: '--cwd',
description: 'A directory to use instead of $PWD',
default: '.',
},
{
name: '--esm',
description: 'Builds ES-2015 bundles for your code',
default: false,
},
{
name: '--clear',
description: 'Clear the console',
default: true,
},
{
name: '--sw',
description: 'Generate and attach a Service Worker',
default: undefined,
},
{
name: '--babelConfig',
description: 'Path to custom Babel config',
default: '.babelrc',
},
{
name: '--rhl',
description: '(Deprecated) use --refresh instead',
default: false,
},
{
name: '--json',
description: 'Generate build stats for bundle analysis',
},
{
name: '--https',
description: 'Run server with HTTPS protocol',
},
{
name: '--key',
description: 'Path to PEM key for custom SSL certificate',
},
{
name: '--cert',
description: 'Path to custom SSL certificate',
},
{
name: '--cacert',
description: 'Path to optional CA certificate override',
},
{
name: '--prerender',
description: 'Pre-render static content on first run',
},
{
name: '--prerenderUrls',
description: 'Path to pre-rendered routes config',
default: 'prerender-urls.json',
},
{
name: '--template',
description: 'Path to custom HTML template',
},
{
name: '--refresh',
description: 'Enables experimental preact-refresh functionality',
default: false,
},
{
name: '-c, --config',
description: 'Path to custom CLI config',
default: 'preact.config.js',
},
{
name: '-H, --host',
description: 'Set server hostname',
default: '0.0.0.0',
},
{
name: '-p, --port',
description: 'Set server port',
default: 8080,
},
];

module.exports = {
command,
options,
};
Loading

0 comments on commit 67fafc8

Please sign in to comment.