"use strict"; function _core() { const data = require("@parcel/core"); _core = function () { return data; }; return data; } function _fs() { const data = require("@parcel/fs"); _fs = function () { return data; }; return data; } function _diagnostic() { const data = _interopRequireDefault(require("@parcel/diagnostic")); _diagnostic = function () { return data; }; return data; } function _utils() { const data = require("@parcel/utils"); _utils = function () { return data; }; return data; } function _events() { const data = require("@parcel/events"); _events = function () { return data; }; return data; } function _logger() { const data = require("@parcel/logger"); _logger = function () { return data; }; return data; } function _chalk() { const data = _interopRequireDefault(require("chalk")); _chalk = function () { return data; }; return data; } function _commander() { const data = _interopRequireDefault(require("commander")); _commander = function () { return data; }; return data; } function _path() { const data = _interopRequireDefault(require("path")); _path = function () { return data; }; return data; } function _getPort() { const data = _interopRequireDefault(require("get-port")); _getPort = function () { return data; }; return data; } var _package = require("../package.json"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } require('v8-compile-cache'); const program = new (_commander().default.Command)(); // Exit codes in response to signals are traditionally // 128 + signal value // https://tldp.org/LDP/abs/html/exitcodes.html const SIGINT_EXIT_CODE = 130; async function logUncaughtError(e) { if (e instanceof _diagnostic().default) { for (let diagnostic of e.diagnostics) { let { message, codeframe, stack, hints, documentation } = await (0, _utils().prettyDiagnostic)(diagnostic); _logger().INTERNAL_ORIGINAL_CONSOLE.error(_chalk().default.red(message)); if (codeframe || stack) { _logger().INTERNAL_ORIGINAL_CONSOLE.error(''); } _logger().INTERNAL_ORIGINAL_CONSOLE.error(codeframe); _logger().INTERNAL_ORIGINAL_CONSOLE.error(stack); if ((stack || codeframe) && hints.length > 0) { _logger().INTERNAL_ORIGINAL_CONSOLE.error(''); } for (let h of hints) { _logger().INTERNAL_ORIGINAL_CONSOLE.error(_chalk().default.blue(h)); } if (documentation) { _logger().INTERNAL_ORIGINAL_CONSOLE.error(_chalk().default.magenta.bold(documentation)); } } } else { _logger().INTERNAL_ORIGINAL_CONSOLE.error(e); } // A hack to definitely ensure we logged the uncaught exception await new Promise(resolve => setTimeout(resolve, 100)); } const handleUncaughtException = async exception => { try { await logUncaughtError(exception); } catch (err) { console.error(exception); console.error(err); } process.exit(1); }; process.on('unhandledRejection', handleUncaughtException); program.storeOptionsAsProperties(); program.version(_package.version); // --no-cache, --cache-dir, --no-source-maps, --no-autoinstall, --global?, --public-url, --log-level // --no-content-hash, --experimental-scope-hoisting, --detailed-report const commonOptions = { '--no-cache': 'disable the filesystem cache', '--config ': 'specify which config to use. can be a path or a package name', '--cache-dir ': 'set the cache directory. defaults to ".parcel-cache"', '--no-source-maps': 'disable sourcemaps', '--target [name]': ['only build given target(s)', (val, list) => list.concat([val]), []], '--log-level ': new (_commander().default.Option)('--log-level ', 'set the log level').choices(['none', 'error', 'warn', 'info', 'verbose']), '--dist-dir ': 'output directory to write to when unspecified by targets', '--no-autoinstall': 'disable autoinstall', '--profile': 'enable build profiling', '-V, --version': 'output the version number', '--detailed-report [count]': ['print the asset timings and sizes in the build report', parseOptionInt], '--reporter ': ['additional reporters to run', (val, acc) => { acc.push(val); return acc; }, []] }; var hmrOptions = { '--no-hmr': 'disable hot module replacement', '-p, --port ': ['set the port to serve on. defaults to $PORT or 1234', process.env.PORT], '--host ': 'set the host to listen on, defaults to listening on all interfaces', '--https': 'serves files over HTTPS', '--cert ': 'path to certificate to use with HTTPS', '--key ': 'path to private key to use with HTTPS', '--hmr-port ': ['hot module replacement port', process.env.HMR_PORT] }; function applyOptions(cmd, options) { for (let opt in options) { const option = options[opt]; if (option instanceof _commander().default.Option) { cmd.addOption(option); } else { cmd.option(opt, ...(Array.isArray(option) ? option : [option])); } } } let serve = program.command('serve [input...]').description('starts a development server').option('--public-url ', 'the path prefix for absolute urls').option('--open [browser]', 'automatically open in specified browser, defaults to default browser').option('--watch-for-stdin', 'exit when stdin closes').option('--lazy', 'Build async bundles on demand, when requested in the browser').action(runCommand); applyOptions(serve, hmrOptions); applyOptions(serve, commonOptions); let watch = program.command('watch [input...]').description('starts the bundler in watch mode').option('--public-url ', 'the path prefix for absolute urls').option('--no-content-hash', 'disable content hashing').option('--watch-for-stdin', 'exit when stdin closes').action(runCommand); applyOptions(watch, hmrOptions); applyOptions(watch, commonOptions); let build = program.command('build [input...]').description('bundles for production').option('--no-optimize', 'disable minification').option('--no-scope-hoist', 'disable scope-hoisting').option('--public-url ', 'the path prefix for absolute urls').option('--no-content-hash', 'disable content hashing').action(runCommand); applyOptions(build, commonOptions); program.command('help [command]').description('display help information for a command').action(function (command) { let cmd = program.commands.find(c => c.name() === command) || program; cmd.help(); }); program.on('--help', function () { _logger().INTERNAL_ORIGINAL_CONSOLE.log(''); _logger().INTERNAL_ORIGINAL_CONSOLE.log(' Run `' + _chalk().default.bold('parcel help ') + '` for more information on specific commands'); _logger().INTERNAL_ORIGINAL_CONSOLE.log(''); }); // Override to output option description if argument was missing _commander().default.Command.prototype.optionMissingArgument = function (option) { _logger().INTERNAL_ORIGINAL_CONSOLE.error("error: option `%s' argument missing", option.flags); _logger().INTERNAL_ORIGINAL_CONSOLE.log(program.createHelp().optionDescription(option)); process.exit(1); }; // Make serve the default command except for --help var args = process.argv; if (args[2] === '--help' || args[2] === '-h') args[2] = 'help'; if (!args[2] || !program.commands.some(c => c.name() === args[2])) { args.splice(2, 0, 'serve'); } program.parse(args); function runCommand(...args) { run(...args).catch(handleUncaughtException); } async function run(entries, _opts, // using pre v7 Commander options as properties command) { if (entries.length === 0) { entries = ['.']; } entries = entries.map(entry => _path().default.resolve(entry)); let Parcel = require('@parcel/core').default; let fs = new (_fs().NodeFS)(); let options = await normalizeOptions(command, fs); let parcel = new Parcel({ entries, // $FlowFixMe[extra-arg] - flow doesn't know about the `paths` option (added in Node v8.9.0) defaultConfig: require.resolve('@parcel/config-default', { paths: [fs.cwd(), __dirname] }), shouldPatchConsole: true, ...options }); let disposable = new (_events().Disposable)(); let unsubscribe; let isExiting; async function exit(exitCode = 0) { if (isExiting) { return; } isExiting = true; if (unsubscribe != null) { await unsubscribe(); } else if (parcel.isProfiling) { await parcel.stopProfiling(); } if (process.stdin.isTTY && process.stdin.isRaw) { // $FlowFixMe process.stdin.setRawMode(false); } disposable.dispose(); process.exit(exitCode); } const isWatching = command.name() === 'watch' || command.name() === 'serve'; if (process.stdin.isTTY) { // $FlowFixMe process.stdin.setRawMode(true); require('readline').emitKeypressEvents(process.stdin); let stream = process.stdin.on('keypress', async (char, key) => { if (!key.ctrl) { return; } switch (key.name) { case 'c': // Detect the ctrl+c key, and gracefully exit after writing the asset graph to the cache. // This is mostly for tools that wrap Parcel as a child process like yarn and npm. // // Setting raw mode prevents SIGINT from being sent in response to ctrl-c: // https://nodejs.org/api/tty.html#tty_readstream_setrawmode_mode // // We don't use the SIGINT event for this because when run inside yarn, the parent // yarn process ends before Parcel and it appears that Parcel has ended while it may still // be cleaning up. Handling events from stdin prevents this impression. // Enqueue a busy message to be shown if Parcel doesn't shut down // within the timeout. setTimeout(() => _logger().INTERNAL_ORIGINAL_CONSOLE.log(_chalk().default.bold.yellowBright('Parcel is shutting down...')), 500); // When watching, a 0 success code is acceptable when Parcel is interrupted with ctrl-c. // When building, fail with a code as if we received a SIGINT. await exit(isWatching ? 0 : SIGINT_EXIT_CODE); break; case 'e': await (parcel.isProfiling ? parcel.stopProfiling() : parcel.startProfiling()); break; case 'y': await parcel.takeHeapSnapshot(); break; } }); disposable.add(() => { stream.destroy(); }); } if (isWatching) { ({ unsubscribe } = await parcel.watch(err => { if (err) { throw err; } })); if (command.open && options.serveOptions) { await (0, _utils().openInBrowser)(`${options.serveOptions.https ? 'https' : 'http'}://${options.serveOptions.host || 'localhost'}:${options.serveOptions.port}`, command.open); } if (command.watchForStdin) { process.stdin.on('end', async () => { _logger().INTERNAL_ORIGINAL_CONSOLE.log('STDIN closed, ending'); await exit(); }); process.stdin.resume(); } // In non-tty cases, respond to SIGINT by cleaning up. Since we're watching, // a 0 success code is acceptable. process.on('SIGINT', exit); process.on('SIGTERM', exit); } else { try { await parcel.run(); } catch (err) { // If an exception is thrown during Parcel.build, it is given to reporters in a // buildFailure event, and has been shown to the user. if (!(err instanceof _core().BuildError)) { await logUncaughtError(err); } await exit(1); } await exit(); } } function parsePort(portValue) { let parsedPort = Number(portValue); // Throw an error if port value is invalid... if (!Number.isInteger(parsedPort)) { throw new Error(`Port ${portValue} is not a valid integer.`); } return parsedPort; } function parseOptionInt(value) { const parsedValue = parseInt(value, 10); if (isNaN(parsedValue)) { throw new (_commander().default.InvalidOptionArgumentError)('Must be an integer.'); } return parsedValue; } async function normalizeOptions(command, inputFS) { var _command$autoinstall, _command$sourceMaps; let nodeEnv; if (command.name() === 'build') { nodeEnv = process.env.NODE_ENV || 'production'; // Autoinstall unless explicitly disabled or we detect a CI environment. command.autoinstall = !(command.autoinstall === false || process.env.CI); } else { nodeEnv = process.env.NODE_ENV || 'development'; } // Set process.env.NODE_ENV to a default if undefined so that it is // available in JS configs and plugins. process.env.NODE_ENV = nodeEnv; let https = !!command.https; if (command.cert && command.key) { https = { cert: command.cert, key: command.key }; } let serveOptions = false; let { host } = command; // Ensure port is valid and available let port = parsePort(command.port || '1234'); let originalPort = port; if (command.name() === 'serve' || command.hmr) { try { port = await (0, _getPort().default)({ port, host }); } catch (err) { throw new (_diagnostic().default)({ diagnostic: { message: `Could not get available port: ${err.message}`, origin: 'parcel', stack: err.stack } }); } if (port !== originalPort) { let errorMessage = `Port "${originalPort}" could not be used`; if (command.port != null) { // Throw the error if the user defined a custom port throw new Error(errorMessage); } else { // Parcel logger is not set up at this point, so just use native INTERNAL_ORIGINAL_CONSOLE _logger().INTERNAL_ORIGINAL_CONSOLE.warn(errorMessage); } } } if (command.name() === 'serve') { let { publicUrl } = command; serveOptions = { https, port, host, publicUrl }; } let hmrOptions = null; if (command.name() !== 'build' && command.hmr !== false) { let hmrport = command.hmrPort ? parsePort(command.hmrPort) : port; hmrOptions = { port: hmrport, host }; } if (command.detailedReport === true) { command.detailedReport = '10'; } let additionalReporters = [{ packageName: '@parcel/reporter-cli', resolveFrom: __filename }, ...command.reporter.map(packageName => ({ packageName, resolveFrom: _path().default.join(inputFS.cwd(), 'index') }))]; let mode = command.name() === 'build' ? 'production' : 'development'; return { shouldDisableCache: command.cache === false, cacheDir: command.cacheDir, config: command.config, mode, hmrOptions, shouldContentHash: hmrOptions ? false : command.contentHash, serveOptions, targets: command.target.length > 0 ? command.target : null, shouldAutoInstall: (_command$autoinstall = command.autoinstall) !== null && _command$autoinstall !== void 0 ? _command$autoinstall : true, logLevel: command.logLevel, shouldProfile: command.profile, shouldBuildLazily: command.lazy, detailedReport: command.detailedReport != null ? { assetsPerBundle: parseInt(command.detailedReport, 10) } : null, env: { NODE_ENV: nodeEnv }, additionalReporters, defaultTargetOptions: { shouldOptimize: command.optimize != null ? command.optimize : mode === 'production', sourceMaps: (_command$sourceMaps = command.sourceMaps) !== null && _command$sourceMaps !== void 0 ? _command$sourceMaps : true, shouldScopeHoist: command.scopeHoist, publicUrl: command.publicUrl, distDir: command.distDir } }; }