UNPKG

15.8 kBJavaScriptView Raw
1"use strict";
2
3function _core() {
4 const data = require("@parcel/core");
5
6 _core = function () {
7 return data;
8 };
9
10 return data;
11}
12
13function _fs() {
14 const data = require("@parcel/fs");
15
16 _fs = function () {
17 return data;
18 };
19
20 return data;
21}
22
23function _diagnostic() {
24 const data = _interopRequireDefault(require("@parcel/diagnostic"));
25
26 _diagnostic = function () {
27 return data;
28 };
29
30 return data;
31}
32
33function _utils() {
34 const data = require("@parcel/utils");
35
36 _utils = function () {
37 return data;
38 };
39
40 return data;
41}
42
43function _events() {
44 const data = require("@parcel/events");
45
46 _events = function () {
47 return data;
48 };
49
50 return data;
51}
52
53function _logger() {
54 const data = require("@parcel/logger");
55
56 _logger = function () {
57 return data;
58 };
59
60 return data;
61}
62
63function _chalk() {
64 const data = _interopRequireDefault(require("chalk"));
65
66 _chalk = function () {
67 return data;
68 };
69
70 return data;
71}
72
73function _commander() {
74 const data = _interopRequireDefault(require("commander"));
75
76 _commander = function () {
77 return data;
78 };
79
80 return data;
81}
82
83function _path() {
84 const data = _interopRequireDefault(require("path"));
85
86 _path = function () {
87 return data;
88 };
89
90 return data;
91}
92
93function _getPort() {
94 const data = _interopRequireDefault(require("get-port"));
95
96 _getPort = function () {
97 return data;
98 };
99
100 return data;
101}
102
103var _package = require("../package.json");
104
105function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
106
107require('v8-compile-cache');
108
109const program = new (_commander().default.Command)(); // Exit codes in response to signals are traditionally
110// 128 + signal value
111// https://tldp.org/LDP/abs/html/exitcodes.html
112
113const SIGINT_EXIT_CODE = 130;
114
115async function logUncaughtError(e) {
116 if (e instanceof _diagnostic().default) {
117 for (let diagnostic of e.diagnostics) {
118 let {
119 message,
120 codeframe,
121 stack,
122 hints,
123 documentation
124 } = await (0, _utils().prettyDiagnostic)(diagnostic);
125
126 _logger().INTERNAL_ORIGINAL_CONSOLE.error(_chalk().default.red(message));
127
128 if (codeframe || stack) {
129 _logger().INTERNAL_ORIGINAL_CONSOLE.error('');
130 }
131
132 _logger().INTERNAL_ORIGINAL_CONSOLE.error(codeframe);
133
134 _logger().INTERNAL_ORIGINAL_CONSOLE.error(stack);
135
136 if ((stack || codeframe) && hints.length > 0) {
137 _logger().INTERNAL_ORIGINAL_CONSOLE.error('');
138 }
139
140 for (let h of hints) {
141 _logger().INTERNAL_ORIGINAL_CONSOLE.error(_chalk().default.blue(h));
142 }
143
144 if (documentation) {
145 _logger().INTERNAL_ORIGINAL_CONSOLE.error(_chalk().default.magenta.bold(documentation));
146 }
147 }
148 } else {
149 _logger().INTERNAL_ORIGINAL_CONSOLE.error(e);
150 } // A hack to definitely ensure we logged the uncaught exception
151
152
153 await new Promise(resolve => setTimeout(resolve, 100));
154}
155
156const handleUncaughtException = async exception => {
157 try {
158 await logUncaughtError(exception);
159 } catch (err) {
160 console.error(exception);
161 console.error(err);
162 }
163
164 process.exit(1);
165};
166
167process.on('unhandledRejection', handleUncaughtException);
168program.storeOptionsAsProperties();
169program.version(_package.version); // --no-cache, --cache-dir, --no-source-maps, --no-autoinstall, --global?, --public-url, --log-level
170// --no-content-hash, --experimental-scope-hoisting, --detailed-report
171
172const commonOptions = {
173 '--no-cache': 'disable the filesystem cache',
174 '--config <path>': 'specify which config to use. can be a path or a package name',
175 '--cache-dir <path>': 'set the cache directory. defaults to ".parcel-cache"',
176 '--no-source-maps': 'disable sourcemaps',
177 '--target [name]': ['only build given target(s)', (val, list) => list.concat([val]), []],
178 '--log-level <level>': new (_commander().default.Option)('--log-level <level>', 'set the log level').choices(['none', 'error', 'warn', 'info', 'verbose']),
179 '--dist-dir <dir>': 'output directory to write to when unspecified by targets',
180 '--no-autoinstall': 'disable autoinstall',
181 '--profile': 'enable build profiling',
182 '-V, --version': 'output the version number',
183 '--detailed-report [count]': ['print the asset timings and sizes in the build report', parseOptionInt],
184 '--reporter <name>': ['additional reporters to run', (val, acc) => {
185 acc.push(val);
186 return acc;
187 }, []]
188};
189var hmrOptions = {
190 '--no-hmr': 'disable hot module replacement',
191 '-p, --port <port>': ['set the port to serve on. defaults to $PORT or 1234', process.env.PORT],
192 '--host <host>': 'set the host to listen on, defaults to listening on all interfaces',
193 '--https': 'serves files over HTTPS',
194 '--cert <path>': 'path to certificate to use with HTTPS',
195 '--key <path>': 'path to private key to use with HTTPS',
196 '--hmr-port <port>': ['hot module replacement port', process.env.HMR_PORT]
197};
198
199function applyOptions(cmd, options) {
200 for (let opt in options) {
201 const option = options[opt];
202
203 if (option instanceof _commander().default.Option) {
204 cmd.addOption(option);
205 } else {
206 cmd.option(opt, ...(Array.isArray(option) ? option : [option]));
207 }
208 }
209}
210
211let serve = program.command('serve [input...]').description('starts a development server').option('--public-url <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);
212applyOptions(serve, hmrOptions);
213applyOptions(serve, commonOptions);
214let watch = program.command('watch [input...]').description('starts the bundler in watch mode').option('--public-url <url>', 'the path prefix for absolute urls').option('--no-content-hash', 'disable content hashing').option('--watch-for-stdin', 'exit when stdin closes').action(runCommand);
215applyOptions(watch, hmrOptions);
216applyOptions(watch, commonOptions);
217let build = program.command('build [input...]').description('bundles for production').option('--no-optimize', 'disable minification').option('--no-scope-hoist', 'disable scope-hoisting').option('--public-url <url>', 'the path prefix for absolute urls').option('--no-content-hash', 'disable content hashing').action(runCommand);
218applyOptions(build, commonOptions);
219program.command('help [command]').description('display help information for a command').action(function (command) {
220 let cmd = program.commands.find(c => c.name() === command) || program;
221 cmd.help();
222});
223program.on('--help', function () {
224 _logger().INTERNAL_ORIGINAL_CONSOLE.log('');
225
226 _logger().INTERNAL_ORIGINAL_CONSOLE.log(' Run `' + _chalk().default.bold('parcel help <command>') + '` for more information on specific commands');
227
228 _logger().INTERNAL_ORIGINAL_CONSOLE.log('');
229}); // Override to output option description if argument was missing
230
231_commander().default.Command.prototype.optionMissingArgument = function (option) {
232 _logger().INTERNAL_ORIGINAL_CONSOLE.error("error: option `%s' argument missing", option.flags);
233
234 _logger().INTERNAL_ORIGINAL_CONSOLE.log(program.createHelp().optionDescription(option));
235
236 process.exit(1);
237}; // Make serve the default command except for --help
238
239
240var args = process.argv;
241if (args[2] === '--help' || args[2] === '-h') args[2] = 'help';
242
243if (!args[2] || !program.commands.some(c => c.name() === args[2])) {
244 args.splice(2, 0, 'serve');
245}
246
247program.parse(args);
248
249function runCommand(...args) {
250 run(...args).catch(handleUncaughtException);
251}
252
253async function run(entries, _opts, // using pre v7 Commander options as properties
254command) {
255 if (entries.length === 0) {
256 entries = ['.'];
257 }
258
259 entries = entries.map(entry => _path().default.resolve(entry));
260
261 let Parcel = require('@parcel/core').default;
262
263 let fs = new (_fs().NodeFS)();
264 let options = await normalizeOptions(command, fs);
265 let parcel = new Parcel({
266 entries,
267 // $FlowFixMe[extra-arg] - flow doesn't know about the `paths` option (added in Node v8.9.0)
268 defaultConfig: require.resolve('@parcel/config-default', {
269 paths: [fs.cwd(), __dirname]
270 }),
271 shouldPatchConsole: true,
272 ...options
273 });
274 let disposable = new (_events().Disposable)();
275 let unsubscribe;
276 let isExiting;
277
278 async function exit(exitCode = 0) {
279 if (isExiting) {
280 return;
281 }
282
283 isExiting = true;
284
285 if (unsubscribe != null) {
286 await unsubscribe();
287 } else if (parcel.isProfiling) {
288 await parcel.stopProfiling();
289 }
290
291 if (process.stdin.isTTY && process.stdin.isRaw) {
292 // $FlowFixMe
293 process.stdin.setRawMode(false);
294 }
295
296 disposable.dispose();
297 process.exit(exitCode);
298 }
299
300 const isWatching = command.name() === 'watch' || command.name() === 'serve';
301
302 if (process.stdin.isTTY) {
303 // $FlowFixMe
304 process.stdin.setRawMode(true);
305
306 require('readline').emitKeypressEvents(process.stdin);
307
308 let stream = process.stdin.on('keypress', async (char, key) => {
309 if (!key.ctrl) {
310 return;
311 }
312
313 switch (key.name) {
314 case 'c':
315 // Detect the ctrl+c key, and gracefully exit after writing the asset graph to the cache.
316 // This is mostly for tools that wrap Parcel as a child process like yarn and npm.
317 //
318 // Setting raw mode prevents SIGINT from being sent in response to ctrl-c:
319 // https://nodejs.org/api/tty.html#tty_readstream_setrawmode_mode
320 //
321 // We don't use the SIGINT event for this because when run inside yarn, the parent
322 // yarn process ends before Parcel and it appears that Parcel has ended while it may still
323 // be cleaning up. Handling events from stdin prevents this impression.
324 // Enqueue a busy message to be shown if Parcel doesn't shut down
325 // within the timeout.
326 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.
327 // When building, fail with a code as if we received a SIGINT.
328
329 await exit(isWatching ? 0 : SIGINT_EXIT_CODE);
330 break;
331
332 case 'e':
333 await (parcel.isProfiling ? parcel.stopProfiling() : parcel.startProfiling());
334 break;
335
336 case 'y':
337 await parcel.takeHeapSnapshot();
338 break;
339 }
340 });
341 disposable.add(() => {
342 stream.destroy();
343 });
344 }
345
346 if (isWatching) {
347 ({
348 unsubscribe
349 } = await parcel.watch(err => {
350 if (err) {
351 throw err;
352 }
353 }));
354
355 if (command.open && options.serveOptions) {
356 await (0, _utils().openInBrowser)(`${options.serveOptions.https ? 'https' : 'http'}://${options.serveOptions.host || 'localhost'}:${options.serveOptions.port}`, command.open);
357 }
358
359 if (command.watchForStdin) {
360 process.stdin.on('end', async () => {
361 _logger().INTERNAL_ORIGINAL_CONSOLE.log('STDIN closed, ending');
362
363 await exit();
364 });
365 process.stdin.resume();
366 } // In non-tty cases, respond to SIGINT by cleaning up. Since we're watching,
367 // a 0 success code is acceptable.
368
369
370 process.on('SIGINT', exit);
371 process.on('SIGTERM', exit);
372 } else {
373 try {
374 await parcel.run();
375 } catch (err) {
376 // If an exception is thrown during Parcel.build, it is given to reporters in a
377 // buildFailure event, and has been shown to the user.
378 if (!(err instanceof _core().BuildError)) {
379 await logUncaughtError(err);
380 }
381
382 await exit(1);
383 }
384
385 await exit();
386 }
387}
388
389function parsePort(portValue) {
390 let parsedPort = Number(portValue); // Throw an error if port value is invalid...
391
392 if (!Number.isInteger(parsedPort)) {
393 throw new Error(`Port ${portValue} is not a valid integer.`);
394 }
395
396 return parsedPort;
397}
398
399function parseOptionInt(value) {
400 const parsedValue = parseInt(value, 10);
401
402 if (isNaN(parsedValue)) {
403 throw new (_commander().default.InvalidOptionArgumentError)('Must be an integer.');
404 }
405
406 return parsedValue;
407}
408
409async function normalizeOptions(command, inputFS) {
410 var _command$autoinstall, _command$sourceMaps;
411
412 let nodeEnv;
413
414 if (command.name() === 'build') {
415 nodeEnv = process.env.NODE_ENV || 'production'; // Autoinstall unless explicitly disabled or we detect a CI environment.
416
417 command.autoinstall = !(command.autoinstall === false || process.env.CI);
418 } else {
419 nodeEnv = process.env.NODE_ENV || 'development';
420 } // Set process.env.NODE_ENV to a default if undefined so that it is
421 // available in JS configs and plugins.
422
423
424 process.env.NODE_ENV = nodeEnv;
425 let https = !!command.https;
426
427 if (command.cert && command.key) {
428 https = {
429 cert: command.cert,
430 key: command.key
431 };
432 }
433
434 let serveOptions = false;
435 let {
436 host
437 } = command; // Ensure port is valid and available
438
439 let port = parsePort(command.port || '1234');
440 let originalPort = port;
441
442 if (command.name() === 'serve' || command.hmr) {
443 try {
444 port = await (0, _getPort().default)({
445 port,
446 host
447 });
448 } catch (err) {
449 throw new (_diagnostic().default)({
450 diagnostic: {
451 message: `Could not get available port: ${err.message}`,
452 origin: 'parcel',
453 stack: err.stack
454 }
455 });
456 }
457
458 if (port !== originalPort) {
459 let errorMessage = `Port "${originalPort}" could not be used`;
460
461 if (command.port != null) {
462 // Throw the error if the user defined a custom port
463 throw new Error(errorMessage);
464 } else {
465 // Parcel logger is not set up at this point, so just use native INTERNAL_ORIGINAL_CONSOLE
466 _logger().INTERNAL_ORIGINAL_CONSOLE.warn(errorMessage);
467 }
468 }
469 }
470
471 if (command.name() === 'serve') {
472 let {
473 publicUrl
474 } = command;
475 serveOptions = {
476 https,
477 port,
478 host,
479 publicUrl
480 };
481 }
482
483 let hmrOptions = null;
484
485 if (command.name() !== 'build' && command.hmr !== false) {
486 let hmrport = command.hmrPort ? parsePort(command.hmrPort) : port;
487 hmrOptions = {
488 port: hmrport,
489 host
490 };
491 }
492
493 if (command.detailedReport === true) {
494 command.detailedReport = '10';
495 }
496
497 let additionalReporters = [{
498 packageName: '@parcel/reporter-cli',
499 resolveFrom: __filename
500 }, ...command.reporter.map(packageName => ({
501 packageName,
502 resolveFrom: _path().default.join(inputFS.cwd(), 'index')
503 }))];
504 let mode = command.name() === 'build' ? 'production' : 'development';
505 return {
506 shouldDisableCache: command.cache === false,
507 cacheDir: command.cacheDir,
508 config: command.config,
509 mode,
510 hmrOptions,
511 shouldContentHash: hmrOptions ? false : command.contentHash,
512 serveOptions,
513 targets: command.target.length > 0 ? command.target : null,
514 shouldAutoInstall: (_command$autoinstall = command.autoinstall) !== null && _command$autoinstall !== void 0 ? _command$autoinstall : true,
515 logLevel: command.logLevel,
516 shouldProfile: command.profile,
517 shouldBuildLazily: command.lazy,
518 detailedReport: command.detailedReport != null ? {
519 assetsPerBundle: parseInt(command.detailedReport, 10)
520 } : null,
521 env: {
522 NODE_ENV: nodeEnv
523 },
524 additionalReporters,
525 defaultTargetOptions: {
526 shouldOptimize: command.optimize != null ? command.optimize : mode === 'production',
527 sourceMaps: (_command$sourceMaps = command.sourceMaps) !== null && _command$sourceMaps !== void 0 ? _command$sourceMaps : true,
528 shouldScopeHoist: command.scopeHoist,
529 publicUrl: command.publicUrl,
530 distDir: command.distDir
531 }
532 };
533}
\No newline at end of file