| /* |
| @license |
| Rollup.js v4.22.4 |
| Sat, 21 Sep 2024 06:10:53 GMT - commit 79c0aba353ca84c0e22c3cfe9eee433ba83f3670 |
| |
| https://github.com/rollup/rollup |
| |
| Released under the MIT License. |
| */ |
| 'use strict'; |
| |
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); |
| |
| const index = require('./index.js'); |
| const promises = require('node:fs/promises'); |
| const process$2 = require('node:process'); |
| const cli = require('../bin/rollup'); |
| const rollup = require('./rollup.js'); |
| const parseAst_js = require('./parseAst.js'); |
| const loadConfigFile_js = require('./loadConfigFile.js'); |
| const node_child_process = require('node:child_process'); |
| const rollup_js = require('../rollup.js'); |
| require('fs'); |
| require('util'); |
| require('stream'); |
| require('path'); |
| require('os'); |
| require('./fsevents-importer.js'); |
| require('events'); |
| require('node:path'); |
| require('tty'); |
| require('../native.js'); |
| require('node:perf_hooks'); |
| require('node:url'); |
| require('../getLogFilter.js'); |
| |
| function timeZone(date = new Date()) { |
| const offset = date.getTimezoneOffset(); |
| const absOffset = Math.abs(offset); |
| const hours = Math.floor(absOffset / 60); |
| const minutes = absOffset % 60; |
| const minutesOut = minutes > 0 ? ':' + ('0' + minutes).slice(-2) : ''; |
| return (offset < 0 ? '+' : '-') + hours + minutesOut; |
| } |
| |
| function dateTime(options = {}) { |
| let { |
| date = new Date(), |
| local = true, |
| showTimeZone = false, |
| showMilliseconds = false |
| } = options; |
| |
| if (local) { |
| // Offset the date so it will return the correct value when getting the ISO string. |
| date = new Date(date.getTime() - (date.getTimezoneOffset() * 60000)); |
| } |
| |
| let end = ''; |
| |
| if (showTimeZone) { |
| end = ' UTC' + (local ? timeZone(date) : ''); |
| } |
| |
| if (showMilliseconds && date.getUTCMilliseconds() > 0) { |
| end = ` ${date.getUTCMilliseconds()}ms${end}`; |
| } |
| |
| return date |
| .toISOString() |
| .replace(/T/, ' ') |
| .replace(/\..+/, end); |
| } |
| |
| /** |
| * This is not the set of all possible signals. |
| * |
| * It IS, however, the set of all signals that trigger |
| * an exit on either Linux or BSD systems. Linux is a |
| * superset of the signal names supported on BSD, and |
| * the unknown signals just fail to register, so we can |
| * catch that easily enough. |
| * |
| * Windows signals are a different set, since there are |
| * signals that terminate Windows processes, but don't |
| * terminate (or don't even exist) on Posix systems. |
| * |
| * Don't bother with SIGKILL. It's uncatchable, which |
| * means that we can't fire any callbacks anyway. |
| * |
| * If a user does happen to register a handler on a non- |
| * fatal signal like SIGWINCH or something, and then |
| * exit, it'll end up firing `process.emit('exit')`, so |
| * the handler will be fired anyway. |
| * |
| * SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised |
| * artificially, inherently leave the process in a |
| * state from which it is not safe to try and enter JS |
| * listeners. |
| */ |
| const signals = []; |
| signals.push('SIGHUP', 'SIGINT', 'SIGTERM'); |
| if (process.platform !== 'win32') { |
| signals.push('SIGALRM', 'SIGABRT', 'SIGVTALRM', 'SIGXCPU', 'SIGXFSZ', 'SIGUSR2', 'SIGTRAP', 'SIGSYS', 'SIGQUIT', 'SIGIOT' |
| // should detect profiler and enable/disable accordingly. |
| // see #21 |
| // 'SIGPROF' |
| ); |
| } |
| if (process.platform === 'linux') { |
| signals.push('SIGIO', 'SIGPOLL', 'SIGPWR', 'SIGSTKFLT'); |
| } |
| |
| // Note: since nyc uses this module to output coverage, any lines |
| // that are in the direct sync flow of nyc's outputCoverage are |
| // ignored, since we can never get coverage for them. |
| // grab a reference to node's real process object right away |
| const processOk = (process) => !!process && |
| typeof process === 'object' && |
| typeof process.removeListener === 'function' && |
| typeof process.emit === 'function' && |
| typeof process.reallyExit === 'function' && |
| typeof process.listeners === 'function' && |
| typeof process.kill === 'function' && |
| typeof process.pid === 'number' && |
| typeof process.on === 'function'; |
| const kExitEmitter = Symbol.for('signal-exit emitter'); |
| const global = globalThis; |
| const ObjectDefineProperty = Object.defineProperty.bind(Object); |
| // teeny special purpose ee |
| class Emitter { |
| emitted = { |
| afterExit: false, |
| exit: false, |
| }; |
| listeners = { |
| afterExit: [], |
| exit: [], |
| }; |
| count = 0; |
| id = Math.random(); |
| constructor() { |
| if (global[kExitEmitter]) { |
| return global[kExitEmitter]; |
| } |
| ObjectDefineProperty(global, kExitEmitter, { |
| value: this, |
| writable: false, |
| enumerable: false, |
| configurable: false, |
| }); |
| } |
| on(ev, fn) { |
| this.listeners[ev].push(fn); |
| } |
| removeListener(ev, fn) { |
| const list = this.listeners[ev]; |
| const i = list.indexOf(fn); |
| /* c8 ignore start */ |
| if (i === -1) { |
| return; |
| } |
| /* c8 ignore stop */ |
| if (i === 0 && list.length === 1) { |
| list.length = 0; |
| } |
| else { |
| list.splice(i, 1); |
| } |
| } |
| emit(ev, code, signal) { |
| if (this.emitted[ev]) { |
| return false; |
| } |
| this.emitted[ev] = true; |
| let ret = false; |
| for (const fn of this.listeners[ev]) { |
| ret = fn(code, signal) === true || ret; |
| } |
| if (ev === 'exit') { |
| ret = this.emit('afterExit', code, signal) || ret; |
| } |
| return ret; |
| } |
| } |
| class SignalExitBase { |
| } |
| const signalExitWrap = (handler) => { |
| return { |
| onExit(cb, opts) { |
| return handler.onExit(cb, opts); |
| }, |
| load() { |
| return handler.load(); |
| }, |
| unload() { |
| return handler.unload(); |
| }, |
| }; |
| }; |
| class SignalExitFallback extends SignalExitBase { |
| onExit() { |
| return () => { }; |
| } |
| load() { } |
| unload() { } |
| } |
| class SignalExit extends SignalExitBase { |
| // "SIGHUP" throws an `ENOSYS` error on Windows, |
| // so use a supported signal instead |
| /* c8 ignore start */ |
| #hupSig = process$1.platform === 'win32' ? 'SIGINT' : 'SIGHUP'; |
| /* c8 ignore stop */ |
| #emitter = new Emitter(); |
| #process; |
| #originalProcessEmit; |
| #originalProcessReallyExit; |
| #sigListeners = {}; |
| #loaded = false; |
| constructor(process) { |
| super(); |
| this.#process = process; |
| // { <signal>: <listener fn>, ... } |
| this.#sigListeners = {}; |
| for (const sig of signals) { |
| this.#sigListeners[sig] = () => { |
| // If there are no other listeners, an exit is coming! |
| // Simplest way: remove us and then re-send the signal. |
| // We know that this will kill the process, so we can |
| // safely emit now. |
| const listeners = this.#process.listeners(sig); |
| let { count } = this.#emitter; |
| // This is a workaround for the fact that signal-exit v3 and signal |
| // exit v4 are not aware of each other, and each will attempt to let |
| // the other handle it, so neither of them do. To correct this, we |
| // detect if we're the only handler *except* for previous versions |
| // of signal-exit, and increment by the count of listeners it has |
| // created. |
| /* c8 ignore start */ |
| const p = process; |
| if (typeof p.__signal_exit_emitter__ === 'object' && |
| typeof p.__signal_exit_emitter__.count === 'number') { |
| count += p.__signal_exit_emitter__.count; |
| } |
| /* c8 ignore stop */ |
| if (listeners.length === count) { |
| this.unload(); |
| const ret = this.#emitter.emit('exit', null, sig); |
| /* c8 ignore start */ |
| const s = sig === 'SIGHUP' ? this.#hupSig : sig; |
| if (!ret) |
| process.kill(process.pid, s); |
| /* c8 ignore stop */ |
| } |
| }; |
| } |
| this.#originalProcessReallyExit = process.reallyExit; |
| this.#originalProcessEmit = process.emit; |
| } |
| onExit(cb, opts) { |
| /* c8 ignore start */ |
| if (!processOk(this.#process)) { |
| return () => { }; |
| } |
| /* c8 ignore stop */ |
| if (this.#loaded === false) { |
| this.load(); |
| } |
| const ev = opts?.alwaysLast ? 'afterExit' : 'exit'; |
| this.#emitter.on(ev, cb); |
| return () => { |
| this.#emitter.removeListener(ev, cb); |
| if (this.#emitter.listeners['exit'].length === 0 && |
| this.#emitter.listeners['afterExit'].length === 0) { |
| this.unload(); |
| } |
| }; |
| } |
| load() { |
| if (this.#loaded) { |
| return; |
| } |
| this.#loaded = true; |
| // This is the number of onSignalExit's that are in play. |
| // It's important so that we can count the correct number of |
| // listeners on signals, and don't wait for the other one to |
| // handle it instead of us. |
| this.#emitter.count += 1; |
| for (const sig of signals) { |
| try { |
| const fn = this.#sigListeners[sig]; |
| if (fn) |
| this.#process.on(sig, fn); |
| } |
| catch (_) { } |
| } |
| this.#process.emit = (ev, ...a) => { |
| return this.#processEmit(ev, ...a); |
| }; |
| this.#process.reallyExit = (code) => { |
| return this.#processReallyExit(code); |
| }; |
| } |
| unload() { |
| if (!this.#loaded) { |
| return; |
| } |
| this.#loaded = false; |
| signals.forEach(sig => { |
| const listener = this.#sigListeners[sig]; |
| /* c8 ignore start */ |
| if (!listener) { |
| throw new Error('Listener not defined for signal: ' + sig); |
| } |
| /* c8 ignore stop */ |
| try { |
| this.#process.removeListener(sig, listener); |
| /* c8 ignore start */ |
| } |
| catch (_) { } |
| /* c8 ignore stop */ |
| }); |
| this.#process.emit = this.#originalProcessEmit; |
| this.#process.reallyExit = this.#originalProcessReallyExit; |
| this.#emitter.count -= 1; |
| } |
| #processReallyExit(code) { |
| /* c8 ignore start */ |
| if (!processOk(this.#process)) { |
| return 0; |
| } |
| this.#process.exitCode = code || 0; |
| /* c8 ignore stop */ |
| this.#emitter.emit('exit', this.#process.exitCode, null); |
| return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode); |
| } |
| #processEmit(ev, ...args) { |
| const og = this.#originalProcessEmit; |
| if (ev === 'exit' && processOk(this.#process)) { |
| if (typeof args[0] === 'number') { |
| this.#process.exitCode = args[0]; |
| /* c8 ignore start */ |
| } |
| /* c8 ignore start */ |
| const ret = og.call(this.#process, ev, ...args); |
| /* c8 ignore start */ |
| this.#emitter.emit('exit', this.#process.exitCode, null); |
| /* c8 ignore stop */ |
| return ret; |
| } |
| else { |
| return og.call(this.#process, ev, ...args); |
| } |
| } |
| } |
| const process$1 = globalThis.process; |
| // wrap so that we call the method on the actual handler, without |
| // exporting it directly. |
| const { |
| /** |
| * Called when the process is exiting, whether via signal, explicit |
| * exit, or running out of stuff to do. |
| * |
| * If the global process object is not suitable for instrumentation, |
| * then this will be a no-op. |
| * |
| * Returns a function that may be used to unload signal-exit. |
| */ |
| onExit, |
| /** |
| * Load the listeners. Likely you never need to call this, unless |
| * doing a rather deep integration with signal-exit functionality. |
| * Mostly exposed for the benefit of testing. |
| * |
| * @internal |
| */ |
| load, |
| /** |
| * Unload the listeners. Likely you never need to call this, unless |
| * doing a rather deep integration with signal-exit functionality. |
| * Mostly exposed for the benefit of testing. |
| * |
| * @internal |
| */ |
| unload, } = signalExitWrap(processOk(process$1) ? new SignalExit(process$1) : new SignalExitFallback()); |
| |
| const CLEAR_SCREEN = '\u001Bc'; |
| function getResetScreen(configs, allowClearScreen) { |
| let clearScreen = allowClearScreen; |
| for (const config of configs) { |
| if (config.watch && config.watch.clearScreen === false) { |
| clearScreen = false; |
| } |
| } |
| if (clearScreen) { |
| return (heading) => rollup.stderr(CLEAR_SCREEN + heading); |
| } |
| let firstRun = true; |
| return (heading) => { |
| if (firstRun) { |
| rollup.stderr(heading); |
| firstRun = false; |
| } |
| }; |
| } |
| |
| function extractWatchHooks(command) { |
| if (!Array.isArray(command.watch)) |
| return {}; |
| return command.watch |
| .filter(value => typeof value === 'object') |
| .reduce((accumulator, keyValueOption) => ({ ...accumulator, ...keyValueOption }), {}); |
| } |
| function createWatchHooks(command) { |
| const watchHooks = extractWatchHooks(command); |
| return function (hook) { |
| if (watchHooks[hook]) { |
| const cmd = watchHooks[hook]; |
| if (!command.silent) { |
| rollup.stderr(rollup.cyan$1(`watch.${hook} ${rollup.bold(`$ ${cmd}`)}`)); |
| } |
| try { |
| // !! important - use stderr for all writes from execSync |
| const stdio = [process.stdin, process.stderr, process.stderr]; |
| node_child_process.execSync(cmd, { stdio: command.silent ? 'ignore' : stdio }); |
| } |
| catch (error) { |
| rollup.stderr(error.message); |
| } |
| } |
| }; |
| } |
| |
| async function watch(command) { |
| process$2.env.ROLLUP_WATCH = 'true'; |
| const isTTY = process$2.stderr.isTTY; |
| const silent = command.silent; |
| let watcher; |
| let configWatcher; |
| let resetScreen; |
| const configFile = command.config ? await cli.getConfigPath(command.config) : null; |
| const runWatchHook = createWatchHooks(command); |
| onExit(close); |
| process$2.on('uncaughtException', closeWithError); |
| if (!process$2.stdin.isTTY) { |
| process$2.stdin.on('end', close); |
| process$2.stdin.resume(); |
| } |
| async function loadConfigFromFileAndTrack(configFile) { |
| let configFileData = null; |
| let configFileRevision = 0; |
| configWatcher = index.chokidar.watch(configFile).on('change', reloadConfigFile); |
| await reloadConfigFile(); |
| async function reloadConfigFile() { |
| try { |
| const newConfigFileData = await promises.readFile(configFile, 'utf8'); |
| if (newConfigFileData === configFileData) { |
| return; |
| } |
| configFileRevision++; |
| const currentConfigFileRevision = configFileRevision; |
| if (configFileData) { |
| rollup.stderr(`\nReloading updated config...`); |
| } |
| configFileData = newConfigFileData; |
| const { options, warnings } = await loadConfigFile_js.loadConfigFile(configFile, command, true); |
| if (currentConfigFileRevision !== configFileRevision) { |
| return; |
| } |
| if (watcher) { |
| await watcher.close(); |
| } |
| start(options, warnings); |
| } |
| catch (error) { |
| rollup.handleError(error, true); |
| } |
| } |
| } |
| if (configFile) { |
| await loadConfigFromFileAndTrack(configFile); |
| } |
| else { |
| const { options, warnings } = await cli.loadConfigFromCommand(command, true); |
| await start(options, warnings); |
| } |
| async function start(configs, warnings) { |
| watcher = rollup_js.watch(configs); |
| watcher.on('event', event => { |
| switch (event.code) { |
| case 'ERROR': { |
| warnings.flush(); |
| rollup.handleError(event.error, true); |
| runWatchHook('onError'); |
| break; |
| } |
| case 'START': { |
| if (!silent) { |
| if (!resetScreen) { |
| resetScreen = getResetScreen(configs, isTTY); |
| } |
| resetScreen(rollup.underline(`rollup v${rollup.version}`)); |
| } |
| runWatchHook('onStart'); |
| break; |
| } |
| case 'BUNDLE_START': { |
| if (!silent) { |
| let input = event.input; |
| if (typeof input !== 'string') { |
| input = Array.isArray(input) |
| ? input.join(', ') |
| : Object.values(input).join(', '); |
| } |
| rollup.stderr(rollup.cyan$1(`bundles ${rollup.bold(input)} → ${rollup.bold(event.output.map(parseAst_js.relativeId).join(', '))}...`)); |
| } |
| runWatchHook('onBundleStart'); |
| break; |
| } |
| case 'BUNDLE_END': { |
| warnings.flush(); |
| if (!silent) |
| rollup.stderr(rollup.green(`created ${rollup.bold(event.output.map(parseAst_js.relativeId).join(', '))} in ${rollup.bold(cli.prettyMilliseconds(event.duration))}`)); |
| runWatchHook('onBundleEnd'); |
| if (event.result && event.result.getTimings) { |
| cli.printTimings(event.result.getTimings()); |
| } |
| break; |
| } |
| case 'END': { |
| runWatchHook('onEnd'); |
| if (!silent && isTTY) { |
| rollup.stderr(`\n[${dateTime()}] waiting for changes...`); |
| } |
| } |
| } |
| if ('result' in event && event.result) { |
| event.result.close().catch(error => rollup.handleError(error, true)); |
| } |
| }); |
| } |
| function close(code) { |
| process$2.removeListener('uncaughtException', closeWithError); |
| // removing a non-existent listener is a no-op |
| process$2.stdin.removeListener('end', close); |
| if (configWatcher) |
| configWatcher.close(); |
| Promise.resolve(watcher?.close()).finally(() => { |
| process$2.exit(typeof code === 'number' ? code : 0); |
| }); |
| // Tell signal-exit that we are handling this gracefully |
| return true; |
| } |
| // return a promise that never resolves to keep the process running |
| return new Promise(() => { }); |
| } |
| function closeWithError(error) { |
| error.name = `Uncaught ${error.name}`; |
| rollup.handleError(error); |
| } |
| |
| exports.watch = watch; |
| //# sourceMappingURL=watch-cli.js.map |