aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/rollup/dist/shared/watch-cli.js
diff options
context:
space:
mode:
Diffstat (limited to 'vanilla/node_modules/rollup/dist/shared/watch-cli.js')
-rw-r--r--vanilla/node_modules/rollup/dist/shared/watch-cli.js542
1 files changed, 542 insertions, 0 deletions
diff --git a/vanilla/node_modules/rollup/dist/shared/watch-cli.js b/vanilla/node_modules/rollup/dist/shared/watch-cli.js
new file mode 100644
index 0000000..ea88437
--- /dev/null
+++ b/vanilla/node_modules/rollup/dist/shared/watch-cli.js
@@ -0,0 +1,542 @@
+/*
+ @license
+ Rollup.js v4.57.1
+ Fri, 30 Jan 2026 08:13:08 GMT - commit d37675f25150d6a94dcf4138853bdc2ecb3ce57b
+
+ 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('path');
+require('fs');
+require('util');
+require('stream');
+require('os');
+require('./fsevents-importer.js');
+require('events');
+require('node:path');
+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} = 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(`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);
+ 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(`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) {
+ 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