es-dev-server
Version:
Development server for modern web apps
233 lines (232 loc) • 8.15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.readCommandLineArgs = exports.commandLineOptions = void 0;
const tslib_1 = require("tslib");
/* eslint-disable import/no-dynamic-require, global-require */
const command_line_args_1 = tslib_1.__importDefault(require("command-line-args"));
const command_line_usage_1 = tslib_1.__importDefault(require("command-line-usage"));
const path_1 = tslib_1.__importDefault(require("path"));
const camelcase_1 = tslib_1.__importDefault(require("camelcase"));
const fs_1 = tslib_1.__importDefault(require("fs"));
const deepmerge_1 = tslib_1.__importDefault(require("deepmerge"));
const utils_1 = require("./utils/utils");
exports.commandLineOptions = [
{
name: 'config',
alias: 'c',
type: String,
description: 'The file to read configuration from (js or json). Config entries are camelCases flags.',
},
{
name: 'port',
alias: 'p',
type: Number,
description: 'The port to use. Default: 8080',
},
{
name: 'hostname',
alias: 'h',
type: String,
description: 'The hostname to use. Default: localhost',
},
{
name: 'open',
alias: 'o',
type: String,
description: 'Opens the browser on app-index, root dir or a custom path.',
},
{
name: 'app-index',
alias: 'a',
type: String,
description: "The app's index.html file. When set, serves the index.html for non-file requests. Use this to enable SPA routing.",
},
{
name: 'root-dir',
alias: 'r',
type: String,
description: 'The root directory to serve files from. Defaults to the current working directory.',
},
{
name: 'base-path',
type: String,
description: 'Base path the app is served on. This path is only visible in the browser, it is stripped from the request url before resolving files. ' +
'Starts with a / and ends with no/. For example: /my-app, /foo, /foo/bar',
},
{
name: 'module-dirs',
alias: 'm',
type: String,
multiple: true,
description: 'Directories to resolve modules from. Used by node-resolve',
},
{
name: 'watch',
alias: 'w',
type: Boolean,
description: 'Reload the browser when files are edited.',
},
{
name: 'watch-excludes',
type: String,
description: 'Globs to exclude from file watching. Default: node_modules/**',
},
{
name: 'http2',
alias: 't',
type: Boolean,
description: 'Serve files over HTTP2. Sets up HTTPS with self-signed certificates or optional custom certificates',
},
{
name: 'ssl-key',
type: String,
description: 'Path to local .key file for https',
},
{
name: 'ssl-cert',
type: String,
description: 'Path to local .cert file for https',
},
{
name: 'cors',
type: Boolean,
description: 'Enable CORS',
},
{
name: 'node-resolve',
alias: 'n',
type: Boolean,
description: 'Resolve bare import imports using node resolve.',
},
{
name: 'dedupe',
alias: 'd',
type: Boolean,
description: 'Dedupe modules by resolving them always from the root, ensuring only one version of a package is ever resolved.',
},
{
name: 'preserve-symlinks',
type: Boolean,
description: 'Preserve symlinks when resolving modules. Default false, which is the default node behavior.',
},
{
name: 'babel',
alias: 'b',
type: Boolean,
description: 'Transform served code through babel. Requires .babelrc',
},
{
name: 'file-extensions',
type: String,
multiple: true,
description: 'Extra file extentions to use when transforming code.',
},
{
name: 'babel-exclude',
type: String,
multiple: true,
description: 'Patterns of files to exclude from babel compilation.',
},
{
name: 'babel-modern-exclude',
type: String,
multiple: true,
description: 'Patterns of files to exclude from babel compilation on modern browsers.',
},
{
name: 'compatibility',
type: String,
description: 'Compatibility mode for older browsers. Can be: "auto", "always", "min", "max" or "none". Default "auto"',
},
{
name: 'event-stream',
type: String,
description: 'Whether to inject event stream script into HTML pages.',
},
{
name: 'debug',
type: Boolean,
description: 'Whether to log debug messages',
},
{ name: 'help', type: Boolean, description: 'See all options' },
];
/**
* Reads command line args from arguments array. Defaults to `process.argv`.
*/
function readCommandLineArgs(argv = process.argv, config = {}) {
const { defaultConfigDir = '.', defaultConfigName = 'es-dev-server.config.js' } = config;
const dashesArgs = command_line_args_1.default(exports.commandLineOptions, { argv, partial: true });
const openInCommandLineArgs = 'open' in dashesArgs;
// convert kebab-case to camelCase
const args = Object.keys(dashesArgs).reduce((acc, key) => {
acc[camelcase_1.default(key)] = dashesArgs[key];
return acc;
}, {});
if (args.debug) {
utils_1.setDebug(true);
}
if ('help' in args) {
/* eslint-disable-next-line no-console */
console.log(command_line_usage_1.default([
{
header: 'es-dev-server',
content: `
A dev server for modern web development workflows.
Usage: \`es-dev-server [options...]\`
`.trim(),
},
{
header: 'Global Options',
optionList: exports.commandLineOptions,
},
]));
process.exit();
}
let options;
if (args.config) {
// read config from user provided path
const configPath = path_1.default.join(process.cwd(), args.config);
if (!fs_1.default.existsSync(configPath) || !fs_1.default.statSync(configPath).isFile()) {
throw new Error(`Did not find any config file at ${configPath}`);
}
const fileConfig = require(configPath);
options = deepmerge_1.default(fileConfig, args);
utils_1.logDebug(`Found a config file at ${configPath}`);
}
else {
// read default config if present
const defaultConfigPath = path_1.default.join(process.cwd(), defaultConfigDir, defaultConfigName);
if (fs_1.default.existsSync(defaultConfigPath) && fs_1.default.statSync(defaultConfigPath).isFile()) {
const fileConfig = require(defaultConfigPath);
options = deepmerge_1.default(fileConfig, args);
utils_1.logDebug(`Found a default config file at ${defaultConfigPath}`);
}
else {
// no file config, just command line args
options = args;
utils_1.logDebug(`Did not find a default config file at ${defaultConfigPath}`);
}
}
let open = options.open;
if (options.dedupe) {
options.dedupeModules = options.dedupe;
delete options.dedupe;
}
// open can be a boolean nor a string. if it's a boolean from command line args,
// it's passed as null. so if it's not a string or boolean type, we check for the
// existence of open in the args object, and treat that as true
if (typeof open !== 'string' && typeof open !== 'boolean' && openInCommandLineArgs) {
open = true;
}
return {
...options,
eventStream: options.eventStream !== 'false',
open,
logStartup: true,
// when used from the command line we log compile errors to the browser,
// not to the terminal for a better UX
logCompileErrors: false,
};
}
exports.readCommandLineArgs = readCommandLineArgs;
//# sourceMappingURL=command-line-args.js.map