watch-cli.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /*
  2. @license
  3. Rollup.js v3.7.4
  4. Tue, 13 Dec 2022 05:29:18 GMT - commit bd3522b33f18001372638263aeb704b76edbf48c
  5. https://github.com/rollup/rollup
  6. Released under the MIT License.
  7. */
  8. 'use strict';
  9. Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  10. const node_fs = require('node:fs');
  11. const process$2 = require('node:process');
  12. const index = require('./index.js');
  13. const cli = require('../bin/rollup');
  14. const rollup = require('./rollup.js');
  15. const require$$0 = require('assert');
  16. const require$$0$1 = require('events');
  17. const loadConfigFile_js = require('./loadConfigFile.js');
  18. const node_child_process = require('node:child_process');
  19. require('fs');
  20. require('util');
  21. require('stream');
  22. require('path');
  23. require('os');
  24. require('node:path');
  25. require('node:perf_hooks');
  26. require('node:crypto');
  27. require('node:events');
  28. require('tty');
  29. require('node:url');
  30. function timeZone(date = new Date()) {
  31. const offset = date.getTimezoneOffset();
  32. const absOffset = Math.abs(offset);
  33. const hours = Math.floor(absOffset / 60);
  34. const minutes = absOffset % 60;
  35. const minutesOut = minutes > 0 ? ':' + ('0' + minutes).slice(-2) : '';
  36. return (offset < 0 ? '+' : '-') + hours + minutesOut;
  37. }
  38. function dateTime(options = {}) {
  39. let {
  40. date = new Date(),
  41. local = true,
  42. showTimeZone = false,
  43. showMilliseconds = false
  44. } = options;
  45. if (local) {
  46. // Offset the date so it will return the correct value when getting the ISO string.
  47. date = new Date(date.getTime() - (date.getTimezoneOffset() * 60000));
  48. }
  49. let end = '';
  50. if (showTimeZone) {
  51. end = ' UTC' + (local ? timeZone(date) : '');
  52. }
  53. if (showMilliseconds && date.getUTCMilliseconds() > 0) {
  54. end = ` ${date.getUTCMilliseconds()}ms${end}`;
  55. }
  56. return date
  57. .toISOString()
  58. .replace(/T/, ' ')
  59. .replace(/\..+/, end);
  60. }
  61. var signalExit = {exports: {}};
  62. var signals$1 = {exports: {}};
  63. var hasRequiredSignals;
  64. function requireSignals () {
  65. if (hasRequiredSignals) return signals$1.exports;
  66. hasRequiredSignals = 1;
  67. (function (module) {
  68. // This is not the set of all possible signals.
  69. //
  70. // It IS, however, the set of all signals that trigger
  71. // an exit on either Linux or BSD systems. Linux is a
  72. // superset of the signal names supported on BSD, and
  73. // the unknown signals just fail to register, so we can
  74. // catch that easily enough.
  75. //
  76. // Don't bother with SIGKILL. It's uncatchable, which
  77. // means that we can't fire any callbacks anyway.
  78. //
  79. // If a user does happen to register a handler on a non-
  80. // fatal signal like SIGWINCH or something, and then
  81. // exit, it'll end up firing `process.emit('exit')`, so
  82. // the handler will be fired anyway.
  83. //
  84. // SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
  85. // artificially, inherently leave the process in a
  86. // state from which it is not safe to try and enter JS
  87. // listeners.
  88. module.exports = [
  89. 'SIGABRT',
  90. 'SIGALRM',
  91. 'SIGHUP',
  92. 'SIGINT',
  93. 'SIGTERM'
  94. ];
  95. if (process.platform !== 'win32') {
  96. module.exports.push(
  97. 'SIGVTALRM',
  98. 'SIGXCPU',
  99. 'SIGXFSZ',
  100. 'SIGUSR2',
  101. 'SIGTRAP',
  102. 'SIGSYS',
  103. 'SIGQUIT',
  104. 'SIGIOT'
  105. // should detect profiler and enable/disable accordingly.
  106. // see #21
  107. // 'SIGPROF'
  108. );
  109. }
  110. if (process.platform === 'linux') {
  111. module.exports.push(
  112. 'SIGIO',
  113. 'SIGPOLL',
  114. 'SIGPWR',
  115. 'SIGSTKFLT',
  116. 'SIGUNUSED'
  117. );
  118. }
  119. } (signals$1));
  120. return signals$1.exports;
  121. }
  122. // Note: since nyc uses this module to output coverage, any lines
  123. // that are in the direct sync flow of nyc's outputCoverage are
  124. // ignored, since we can never get coverage for them.
  125. // grab a reference to node's real process object right away
  126. var process$1 = rollup.commonjsGlobal.process;
  127. const processOk = function (process) {
  128. return process &&
  129. typeof process === 'object' &&
  130. typeof process.removeListener === 'function' &&
  131. typeof process.emit === 'function' &&
  132. typeof process.reallyExit === 'function' &&
  133. typeof process.listeners === 'function' &&
  134. typeof process.kill === 'function' &&
  135. typeof process.pid === 'number' &&
  136. typeof process.on === 'function'
  137. };
  138. // some kind of non-node environment, just no-op
  139. /* istanbul ignore if */
  140. if (!processOk(process$1)) {
  141. signalExit.exports = function () {
  142. return function () {}
  143. };
  144. } else {
  145. var assert = require$$0;
  146. var signals = requireSignals();
  147. var isWin = /^win/i.test(process$1.platform);
  148. var EE = require$$0$1;
  149. /* istanbul ignore if */
  150. if (typeof EE !== 'function') {
  151. EE = EE.EventEmitter;
  152. }
  153. var emitter;
  154. if (process$1.__signal_exit_emitter__) {
  155. emitter = process$1.__signal_exit_emitter__;
  156. } else {
  157. emitter = process$1.__signal_exit_emitter__ = new EE();
  158. emitter.count = 0;
  159. emitter.emitted = {};
  160. }
  161. // Because this emitter is a global, we have to check to see if a
  162. // previous version of this library failed to enable infinite listeners.
  163. // I know what you're about to say. But literally everything about
  164. // signal-exit is a compromise with evil. Get used to it.
  165. if (!emitter.infinite) {
  166. emitter.setMaxListeners(Infinity);
  167. emitter.infinite = true;
  168. }
  169. signalExit.exports = function (cb, opts) {
  170. /* istanbul ignore if */
  171. if (!processOk(rollup.commonjsGlobal.process)) {
  172. return function () {}
  173. }
  174. assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler');
  175. if (loaded === false) {
  176. load();
  177. }
  178. var ev = 'exit';
  179. if (opts && opts.alwaysLast) {
  180. ev = 'afterexit';
  181. }
  182. var remove = function () {
  183. emitter.removeListener(ev, cb);
  184. if (emitter.listeners('exit').length === 0 &&
  185. emitter.listeners('afterexit').length === 0) {
  186. unload();
  187. }
  188. };
  189. emitter.on(ev, cb);
  190. return remove
  191. };
  192. var unload = function unload () {
  193. if (!loaded || !processOk(rollup.commonjsGlobal.process)) {
  194. return
  195. }
  196. loaded = false;
  197. signals.forEach(function (sig) {
  198. try {
  199. process$1.removeListener(sig, sigListeners[sig]);
  200. } catch (er) {}
  201. });
  202. process$1.emit = originalProcessEmit;
  203. process$1.reallyExit = originalProcessReallyExit;
  204. emitter.count -= 1;
  205. };
  206. signalExit.exports.unload = unload;
  207. var emit = function emit (event, code, signal) {
  208. /* istanbul ignore if */
  209. if (emitter.emitted[event]) {
  210. return
  211. }
  212. emitter.emitted[event] = true;
  213. emitter.emit(event, code, signal);
  214. };
  215. // { <signal>: <listener fn>, ... }
  216. var sigListeners = {};
  217. signals.forEach(function (sig) {
  218. sigListeners[sig] = function listener () {
  219. /* istanbul ignore if */
  220. if (!processOk(rollup.commonjsGlobal.process)) {
  221. return
  222. }
  223. // If there are no other listeners, an exit is coming!
  224. // Simplest way: remove us and then re-send the signal.
  225. // We know that this will kill the process, so we can
  226. // safely emit now.
  227. var listeners = process$1.listeners(sig);
  228. if (listeners.length === emitter.count) {
  229. unload();
  230. emit('exit', null, sig);
  231. /* istanbul ignore next */
  232. emit('afterexit', null, sig);
  233. /* istanbul ignore next */
  234. if (isWin && sig === 'SIGHUP') {
  235. // "SIGHUP" throws an `ENOSYS` error on Windows,
  236. // so use a supported signal instead
  237. sig = 'SIGINT';
  238. }
  239. /* istanbul ignore next */
  240. process$1.kill(process$1.pid, sig);
  241. }
  242. };
  243. });
  244. signalExit.exports.signals = function () {
  245. return signals
  246. };
  247. var loaded = false;
  248. var load = function load () {
  249. if (loaded || !processOk(rollup.commonjsGlobal.process)) {
  250. return
  251. }
  252. loaded = true;
  253. // This is the number of onSignalExit's that are in play.
  254. // It's important so that we can count the correct number of
  255. // listeners on signals, and don't wait for the other one to
  256. // handle it instead of us.
  257. emitter.count += 1;
  258. signals = signals.filter(function (sig) {
  259. try {
  260. process$1.on(sig, sigListeners[sig]);
  261. return true
  262. } catch (er) {
  263. return false
  264. }
  265. });
  266. process$1.emit = processEmit;
  267. process$1.reallyExit = processReallyExit;
  268. };
  269. signalExit.exports.load = load;
  270. var originalProcessReallyExit = process$1.reallyExit;
  271. var processReallyExit = function processReallyExit (code) {
  272. /* istanbul ignore if */
  273. if (!processOk(rollup.commonjsGlobal.process)) {
  274. return
  275. }
  276. process$1.exitCode = code || /* istanbul ignore next */ 0;
  277. emit('exit', process$1.exitCode, null);
  278. /* istanbul ignore next */
  279. emit('afterexit', process$1.exitCode, null);
  280. /* istanbul ignore next */
  281. originalProcessReallyExit.call(process$1, process$1.exitCode);
  282. };
  283. var originalProcessEmit = process$1.emit;
  284. var processEmit = function processEmit (ev, arg) {
  285. if (ev === 'exit' && processOk(rollup.commonjsGlobal.process)) {
  286. /* istanbul ignore else */
  287. if (arg !== undefined) {
  288. process$1.exitCode = arg;
  289. }
  290. var ret = originalProcessEmit.apply(this, arguments);
  291. /* istanbul ignore next */
  292. emit('exit', process$1.exitCode, null);
  293. /* istanbul ignore next */
  294. emit('afterexit', process$1.exitCode, null);
  295. /* istanbul ignore next */
  296. return ret
  297. } else {
  298. return originalProcessEmit.apply(this, arguments)
  299. }
  300. };
  301. }
  302. const CLEAR_SCREEN = '\u001Bc';
  303. function getResetScreen(configs, allowClearScreen) {
  304. let clearScreen = allowClearScreen;
  305. for (const config of configs) {
  306. if (config.watch && config.watch.clearScreen === false) {
  307. clearScreen = false;
  308. }
  309. }
  310. if (clearScreen) {
  311. return (heading) => rollup.stderr(CLEAR_SCREEN + heading);
  312. }
  313. let firstRun = true;
  314. return (heading) => {
  315. if (firstRun) {
  316. rollup.stderr(heading);
  317. firstRun = false;
  318. }
  319. };
  320. }
  321. function extractWatchHooks(command) {
  322. if (!Array.isArray(command.watch))
  323. return {};
  324. return command.watch
  325. .filter(value => typeof value === 'object')
  326. .reduce((accumulator, keyValueOption) => ({ ...accumulator, ...keyValueOption }), {});
  327. }
  328. function createWatchHooks(command) {
  329. const watchHooks = extractWatchHooks(command);
  330. return function (hook) {
  331. if (watchHooks[hook]) {
  332. const cmd = watchHooks[hook];
  333. if (!command.silent) {
  334. rollup.stderr(rollup.cyan(`watch.${hook} ${rollup.bold(`$ ${cmd}`)}`));
  335. }
  336. try {
  337. // !! important - use stderr for all writes from execSync
  338. const stdio = [process.stdin, process.stderr, process.stderr];
  339. node_child_process.execSync(cmd, { stdio: command.silent ? 'ignore' : stdio });
  340. }
  341. catch (error) {
  342. rollup.stderr(error.message);
  343. }
  344. }
  345. };
  346. }
  347. async function watch(command) {
  348. process$2.env.ROLLUP_WATCH = 'true';
  349. const isTTY = process$2.stderr.isTTY;
  350. const silent = command.silent;
  351. let watcher;
  352. let configWatcher;
  353. let resetScreen;
  354. const configFile = command.config ? await cli.getConfigPath(command.config) : null;
  355. const runWatchHook = createWatchHooks(command);
  356. signalExit.exports(close);
  357. process$2.on('uncaughtException', close);
  358. if (!process$2.stdin.isTTY) {
  359. process$2.stdin.on('end', close);
  360. process$2.stdin.resume();
  361. }
  362. async function loadConfigFromFileAndTrack(configFile) {
  363. let configFileData = null;
  364. let configFileRevision = 0;
  365. configWatcher = index.chokidar.watch(configFile).on('change', reloadConfigFile);
  366. await reloadConfigFile();
  367. async function reloadConfigFile() {
  368. try {
  369. const newConfigFileData = await node_fs.promises.readFile(configFile, 'utf8');
  370. if (newConfigFileData === configFileData) {
  371. return;
  372. }
  373. configFileRevision++;
  374. const currentConfigFileRevision = configFileRevision;
  375. if (configFileData) {
  376. rollup.stderr(`\nReloading updated config...`);
  377. }
  378. configFileData = newConfigFileData;
  379. const { options, warnings } = await loadConfigFile_js.loadConfigFile(configFile, command);
  380. if (currentConfigFileRevision !== configFileRevision) {
  381. return;
  382. }
  383. if (watcher) {
  384. await watcher.close();
  385. }
  386. start(options, warnings);
  387. }
  388. catch (error) {
  389. rollup.handleError(error, true);
  390. }
  391. }
  392. }
  393. if (configFile) {
  394. await loadConfigFromFileAndTrack(configFile);
  395. }
  396. else {
  397. const { options, warnings } = await cli.loadConfigFromCommand(command);
  398. await start(options, warnings);
  399. }
  400. async function start(configs, warnings) {
  401. watcher = rollup.watch(configs);
  402. watcher.on('event', event => {
  403. switch (event.code) {
  404. case 'ERROR': {
  405. warnings.flush();
  406. rollup.handleError(event.error, true);
  407. runWatchHook('onError');
  408. break;
  409. }
  410. case 'START': {
  411. if (!silent) {
  412. if (!resetScreen) {
  413. resetScreen = getResetScreen(configs, isTTY);
  414. }
  415. resetScreen(rollup.underline(`rollup v${rollup.version}`));
  416. }
  417. runWatchHook('onStart');
  418. break;
  419. }
  420. case 'BUNDLE_START': {
  421. if (!silent) {
  422. let input = event.input;
  423. if (typeof input !== 'string') {
  424. input = Array.isArray(input)
  425. ? input.join(', ')
  426. : Object.values(input).join(', ');
  427. }
  428. rollup.stderr(rollup.cyan(`bundles ${rollup.bold(input)} → ${rollup.bold(event.output.map(rollup.relativeId).join(', '))}...`));
  429. }
  430. runWatchHook('onBundleStart');
  431. break;
  432. }
  433. case 'BUNDLE_END': {
  434. warnings.flush();
  435. if (!silent)
  436. rollup.stderr(rollup.green(`created ${rollup.bold(event.output.map(rollup.relativeId).join(', '))} in ${rollup.bold(cli.prettyMilliseconds(event.duration))}`));
  437. runWatchHook('onBundleEnd');
  438. if (event.result && event.result.getTimings) {
  439. cli.printTimings(event.result.getTimings());
  440. }
  441. break;
  442. }
  443. case 'END': {
  444. runWatchHook('onEnd');
  445. if (!silent && isTTY) {
  446. rollup.stderr(`\n[${dateTime()}] waiting for changes...`);
  447. }
  448. }
  449. }
  450. if ('result' in event && event.result) {
  451. event.result.close().catch(error => rollup.handleError(error, true));
  452. }
  453. });
  454. }
  455. async function close(code) {
  456. process$2.removeListener('uncaughtException', close);
  457. // removing a non-existent listener is a no-op
  458. process$2.stdin.removeListener('end', close);
  459. if (watcher)
  460. await watcher.close();
  461. if (configWatcher)
  462. configWatcher.close();
  463. if (code) {
  464. // eslint-disable-next-line unicorn/no-process-exit
  465. process$2.exit(code);
  466. }
  467. }
  468. }
  469. exports.watch = watch;
  470. //# sourceMappingURL=watch-cli.js.map