/* @license Rollup.js v2.41.5 Thu, 18 Mar 2021 05:07:55 GMT - commit e2ae914dfe84fd9601743e7ce15841bb483146c4 https://github.com/rollup/rollup Released under the MIT License. */ 'use strict'; var path = require('path'); var require$$0 = require('util'); var index = require('./index.js'); var rollup = require('./rollup.js'); var mergeOptions = require('./mergeOptions.js'); var require$$2 = require('os'); require('events'); require('fs'); require('stream'); require('crypto'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { n[k] = e[k]; }); } n['default'] = e; return n; } var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path); const util = require$$0; const braces = index.braces_1; const picomatch = index.picomatch; const utils = index.utils; const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); /** * Returns an array of strings that match one or more glob patterns. * * ```js * const mm = require('micromatch'); * // mm(list, patterns[, options]); * * console.log(mm(['a.js', 'a.txt'], ['*.js'])); * //=> [ 'a.js' ] * ``` * @param {String|Array} list List of strings to match. * @param {String|Array} patterns One or more glob patterns to use for matching. * @param {Object} options See available [options](#options) * @return {Array} Returns an array of matches * @summary false * @api public */ const micromatch = (list, patterns, options) => { patterns = [].concat(patterns); list = [].concat(list); let omit = new Set(); let keep = new Set(); let items = new Set(); let negatives = 0; let onResult = state => { items.add(state.output); if (options && options.onResult) { options.onResult(state); } }; for (let i = 0; i < patterns.length; i++) { let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true); let negated = isMatch.state.negated || isMatch.state.negatedExtglob; if (negated) negatives++; for (let item of list) { let matched = isMatch(item, true); let match = negated ? !matched.isMatch : matched.isMatch; if (!match) continue; if (negated) { omit.add(matched.output); } else { omit.delete(matched.output); keep.add(matched.output); } } } let result = negatives === patterns.length ? [...items] : [...keep]; let matches = result.filter(item => !omit.has(item)); if (options && matches.length === 0) { if (options.failglob === true) { throw new Error(`No matches found for "${patterns.join(', ')}"`); } if (options.nonull === true || options.nullglob === true) { return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns; } } return matches; }; /** * Backwards compatibility */ micromatch.match = micromatch; /** * Returns a matcher function from the given glob `pattern` and `options`. * The returned function takes a string to match as its only argument and returns * true if the string is a match. * * ```js * const mm = require('micromatch'); * // mm.matcher(pattern[, options]); * * const isMatch = mm.matcher('*.!(*a)'); * console.log(isMatch('a.a')); //=> false * console.log(isMatch('a.b')); //=> true * ``` * @param {String} `pattern` Glob pattern * @param {Object} `options` * @return {Function} Returns a matcher function. * @api public */ micromatch.matcher = (pattern, options) => picomatch(pattern, options); /** * Returns true if **any** of the given glob `patterns` match the specified `string`. * * ```js * const mm = require('micromatch'); * // mm.isMatch(string, patterns[, options]); * * console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true * console.log(mm.isMatch('a.a', 'b.*')); //=> false * ``` * @param {String} str The string to test. * @param {String|Array} patterns One or more glob patterns to use for matching. * @param {Object} [options] See available [options](#options). * @return {Boolean} Returns true if any patterns match `str` * @api public */ micromatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); /** * Backwards compatibility */ micromatch.any = micromatch.isMatch; /** * Returns a list of strings that _**do not match any**_ of the given `patterns`. * * ```js * const mm = require('micromatch'); * // mm.not(list, patterns[, options]); * * console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); * //=> ['b.b', 'c.c'] * ``` * @param {Array} `list` Array of strings to match. * @param {String|Array} `patterns` One or more glob pattern to use for matching. * @param {Object} `options` See available [options](#options) for changing how matches are performed * @return {Array} Returns an array of strings that **do not match** the given patterns. * @api public */ micromatch.not = (list, patterns, options = {}) => { patterns = [].concat(patterns).map(String); let result = new Set(); let items = []; let onResult = state => { if (options.onResult) options.onResult(state); items.push(state.output); }; let matches = micromatch(list, patterns, { ...options, onResult }); for (let item of items) { if (!matches.includes(item)) { result.add(item); } } return [...result]; }; /** * Returns true if the given `string` contains the given pattern. Similar * to [.isMatch](#isMatch) but the pattern can match any part of the string. * * ```js * var mm = require('micromatch'); * // mm.contains(string, pattern[, options]); * * console.log(mm.contains('aa/bb/cc', '*b')); * //=> true * console.log(mm.contains('aa/bb/cc', '*d')); * //=> false * ``` * @param {String} `str` The string to match. * @param {String|Array} `patterns` Glob pattern to use for matching. * @param {Object} `options` See available [options](#options) for changing how matches are performed * @return {Boolean} Returns true if the patter matches any part of `str`. * @api public */ micromatch.contains = (str, pattern, options) => { if (typeof str !== 'string') { throw new TypeError(`Expected a string: "${util.inspect(str)}"`); } if (Array.isArray(pattern)) { return pattern.some(p => micromatch.contains(str, p, options)); } if (typeof pattern === 'string') { if (isEmptyString(str) || isEmptyString(pattern)) { return false; } if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) { return true; } } return micromatch.isMatch(str, pattern, { ...options, contains: true }); }; /** * Filter the keys of the given object with the given `glob` pattern * and `options`. Does not attempt to match nested keys. If you need this feature, * use [glob-object][] instead. * * ```js * const mm = require('micromatch'); * // mm.matchKeys(object, patterns[, options]); * * const obj = { aa: 'a', ab: 'b', ac: 'c' }; * console.log(mm.matchKeys(obj, '*b')); * //=> { ab: 'b' } * ``` * @param {Object} `object` The object with keys to filter. * @param {String|Array} `patterns` One or more glob patterns to use for matching. * @param {Object} `options` See available [options](#options) for changing how matches are performed * @return {Object} Returns an object with only keys that match the given patterns. * @api public */ micromatch.matchKeys = (obj, patterns, options) => { if (!utils.isObject(obj)) { throw new TypeError('Expected the first argument to be an object'); } let keys = micromatch(Object.keys(obj), patterns, options); let res = {}; for (let key of keys) res[key] = obj[key]; return res; }; /** * Returns true if some of the strings in the given `list` match any of the given glob `patterns`. * * ```js * const mm = require('micromatch'); * // mm.some(list, patterns[, options]); * * console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); * // true * console.log(mm.some(['foo.js'], ['*.js', '!foo.js'])); * // false * ``` * @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found. * @param {String|Array} `patterns` One or more glob patterns to use for matching. * @param {Object} `options` See available [options](#options) for changing how matches are performed * @return {Boolean} Returns true if any patterns match `str` * @api public */ micromatch.some = (list, patterns, options) => { let items = [].concat(list); for (let pattern of [].concat(patterns)) { let isMatch = picomatch(String(pattern), options); if (items.some(item => isMatch(item))) { return true; } } return false; }; /** * Returns true if every string in the given `list` matches * any of the given glob `patterns`. * * ```js * const mm = require('micromatch'); * // mm.every(list, patterns[, options]); * * console.log(mm.every('foo.js', ['foo.js'])); * // true * console.log(mm.every(['foo.js', 'bar.js'], ['*.js'])); * // true * console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); * // false * console.log(mm.every(['foo.js'], ['*.js', '!foo.js'])); * // false * ``` * @param {String|Array} `list` The string or array of strings to test. * @param {String|Array} `patterns` One or more glob patterns to use for matching. * @param {Object} `options` See available [options](#options) for changing how matches are performed * @return {Boolean} Returns true if any patterns match `str` * @api public */ micromatch.every = (list, patterns, options) => { let items = [].concat(list); for (let pattern of [].concat(patterns)) { let isMatch = picomatch(String(pattern), options); if (!items.every(item => isMatch(item))) { return false; } } return true; }; /** * Returns true if **all** of the given `patterns` match * the specified string. * * ```js * const mm = require('micromatch'); * // mm.all(string, patterns[, options]); * * console.log(mm.all('foo.js', ['foo.js'])); * // true * * console.log(mm.all('foo.js', ['*.js', '!foo.js'])); * // false * * console.log(mm.all('foo.js', ['*.js', 'foo.js'])); * // true * * console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js'])); * // true * ``` * @param {String|Array} `str` The string to test. * @param {String|Array} `patterns` One or more glob patterns to use for matching. * @param {Object} `options` See available [options](#options) for changing how matches are performed * @return {Boolean} Returns true if any patterns match `str` * @api public */ micromatch.all = (str, patterns, options) => { if (typeof str !== 'string') { throw new TypeError(`Expected a string: "${util.inspect(str)}"`); } return [].concat(patterns).every(p => picomatch(p, options)(str)); }; /** * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match. * * ```js * const mm = require('micromatch'); * // mm.capture(pattern, string[, options]); * * console.log(mm.capture('test/*.js', 'test/foo.js')); * //=> ['foo'] * console.log(mm.capture('test/*.js', 'foo/bar.css')); * //=> null * ``` * @param {String} `glob` Glob pattern to use for matching. * @param {String} `input` String to match * @param {Object} `options` See available [options](#options) for changing how matches are performed * @return {Boolean} Returns an array of captures if the input matches the glob pattern, otherwise `null`. * @api public */ micromatch.capture = (glob, input, options) => { let posix = utils.isWindows(options); let regex = picomatch.makeRe(String(glob), { ...options, capture: true }); let match = regex.exec(posix ? utils.toPosixSlashes(input) : input); if (match) { return match.slice(1).map(v => v === void 0 ? '' : v); } }; /** * Create a regular expression from the given glob `pattern`. * * ```js * const mm = require('micromatch'); * // mm.makeRe(pattern[, options]); * * console.log(mm.makeRe('*.js')); * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ * ``` * @param {String} `pattern` A glob pattern to convert to regex. * @param {Object} `options` * @return {RegExp} Returns a regex created from the given pattern. * @api public */ micromatch.makeRe = (...args) => picomatch.makeRe(...args); /** * Scan a glob pattern to separate the pattern into segments. Used * by the [split](#split) method. * * ```js * const mm = require('micromatch'); * const state = mm.scan(pattern[, options]); * ``` * @param {String} `pattern` * @param {Object} `options` * @return {Object} Returns an object with * @api public */ micromatch.scan = (...args) => picomatch.scan(...args); /** * Parse a glob pattern to create the source string for a regular * expression. * * ```js * const mm = require('micromatch'); * const state = mm(pattern[, options]); * ``` * @param {String} `glob` * @param {Object} `options` * @return {Object} Returns an object with useful properties and output to be used as regex source string. * @api public */ micromatch.parse = (patterns, options) => { let res = []; for (let pattern of [].concat(patterns || [])) { for (let str of braces(String(pattern), options)) { res.push(picomatch.parse(str, options)); } } return res; }; /** * Process the given brace `pattern`. * * ```js * const { braces } = require('micromatch'); * console.log(braces('foo/{a,b,c}/bar')); * //=> [ 'foo/(a|b|c)/bar' ] * * console.log(braces('foo/{a,b,c}/bar', { expand: true })); * //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ] * ``` * @param {String} `pattern` String with brace pattern to process. * @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options. * @return {Array} * @api public */ micromatch.braces = (pattern, options) => { if (typeof pattern !== 'string') throw new TypeError('Expected a string'); if ((options && options.nobrace === true) || !/\{.*\}/.test(pattern)) { return [pattern]; } return braces(pattern, options); }; /** * Expand braces */ micromatch.braceExpand = (pattern, options) => { if (typeof pattern !== 'string') throw new TypeError('Expected a string'); return micromatch.braces(pattern, { ...options, expand: true }); }; /** * Expose micromatch */ var micromatch_1 = micromatch; function ensureArray(thing) { if (Array.isArray(thing)) return thing; if (thing == undefined) return []; return [thing]; } function getMatcherString(id, resolutionBase) { if (resolutionBase === false) { return id; } return path.resolve(...(typeof resolutionBase === 'string' ? [resolutionBase, id] : [id])); } const createFilter = function createFilter(include, exclude, options) { const resolutionBase = options && options.resolve; const getMatcher = (id) => { return id instanceof RegExp ? id : { test: micromatch_1.matcher(getMatcherString(id, resolutionBase) .split(path.sep) .join('/'), { dot: true }) }; }; const includeMatchers = ensureArray(include).map(getMatcher); const excludeMatchers = ensureArray(exclude).map(getMatcher); return function (id) { if (typeof id !== 'string') return false; if (/\0/.test(id)) return false; id = id.split(path.sep).join('/'); for (let i = 0; i < excludeMatchers.length; ++i) { const matcher = excludeMatchers[i]; if (matcher.test(id)) return false; } for (let i = 0; i < includeMatchers.length; ++i) { const matcher = includeMatchers[i]; if (matcher.test(id)) return true; } return !includeMatchers.length; }; }; class FileWatcher { constructor(task, chokidarOptions) { this.transformWatchers = new Map(); this.chokidarOptions = chokidarOptions; this.task = task; this.watcher = this.createWatcher(null); } close() { this.watcher.close(); for (const watcher of this.transformWatchers.values()) { watcher.close(); } } unwatch(id) { this.watcher.unwatch(id); const transformWatcher = this.transformWatchers.get(id); if (transformWatcher) { this.transformWatchers.delete(id); transformWatcher.close(); } } watch(id, isTransformDependency) { if (isTransformDependency) { const watcher = this.transformWatchers.get(id) || this.createWatcher(id); watcher.add(id); this.transformWatchers.set(id, watcher); } else { this.watcher.add(id); } } createWatcher(transformWatcherId) { const task = this.task; const isLinux = require$$2.platform() === 'linux'; const isTransformDependency = transformWatcherId !== null; const handleChange = (id, event) => { const changedId = transformWatcherId || id; if (isLinux) { // unwatching and watching fixes an issue with chokidar where on certain systems, // a file that was unlinked and immediately recreated would create a change event // but then no longer any further events watcher.unwatch(changedId); watcher.add(changedId); } task.invalidate(changedId, { isTransformDependency, event }); }; const watcher = index.chokidar .watch([], this.chokidarOptions) .on('add', id => handleChange(id, 'create')) .on('change', id => handleChange(id, 'update')) .on('unlink', id => handleChange(id, 'delete')); return watcher; } } const eventsRewrites = { create: { create: 'buggy', delete: null, update: 'create' }, delete: { create: 'update', delete: 'buggy', update: 'buggy' }, update: { create: 'buggy', delete: 'delete', update: 'update' } }; class Watcher { constructor(configs, emitter) { this.buildDelay = 0; this.buildTimeout = null; this.invalidatedIds = new Map(); this.rerun = false; this.emitter = emitter; emitter.close = this.close.bind(this); this.tasks = configs.map(config => new Task(this, config)); this.buildDelay = configs.reduce((buildDelay, { watch }) => watch && typeof watch.buildDelay === 'number' ? Math.max(buildDelay, watch.buildDelay) : buildDelay, this.buildDelay); this.running = true; process.nextTick(() => this.run()); } close() { if (this.buildTimeout) clearTimeout(this.buildTimeout); for (const task of this.tasks) { task.close(); } this.emitter.emit('close'); this.emitter.removeAllListeners(); } invalidate(file) { if (file) { const prevEvent = this.invalidatedIds.get(file.id); const event = prevEvent ? eventsRewrites[prevEvent][file.event] : file.event; if (event === 'buggy') { //TODO: throws or warn? Currently just ignore, uses new event this.invalidatedIds.set(file.id, file.event); } else if (event === null) { this.invalidatedIds.delete(file.id); } else { this.invalidatedIds.set(file.id, event); } } if (this.running) { this.rerun = true; return; } if (this.buildTimeout) clearTimeout(this.buildTimeout); this.buildTimeout = setTimeout(() => { this.buildTimeout = null; for (const [id, event] of this.invalidatedIds.entries()) { this.emitter.emit('change', id, { event }); } this.invalidatedIds.clear(); this.emitter.emit('restart'); this.run(); }, this.buildDelay); } async run() { this.running = true; this.emitter.emit('event', { code: 'START' }); for (const task of this.tasks) { await task.run(); } this.running = false; this.emitter.emit('event', { code: 'END' }); if (this.rerun) { this.rerun = false; this.invalidate(); } } } class Task { constructor(watcher, config) { this.cache = { modules: [] }; this.watchFiles = []; this.invalidated = true; this.watcher = watcher; this.closed = false; this.watched = new Set(); this.skipWrite = Boolean(config.watch && config.watch.skipWrite); this.options = mergeOptions.mergeOptions(config); this.outputs = this.options.output; this.outputFiles = this.outputs.map(output => { if (output.file || output.dir) return path__namespace.resolve(output.file || output.dir); return undefined; }); const watchOptions = this.options.watch || {}; this.filter = createFilter(watchOptions.include, watchOptions.exclude); this.fileWatcher = new FileWatcher(this, { ...watchOptions.chokidar, disableGlobbing: true, ignoreInitial: true }); } close() { this.closed = true; this.fileWatcher.close(); } invalidate(id, details) { this.invalidated = true; if (details.isTransformDependency) { for (const module of this.cache.modules) { if (module.transformDependencies.indexOf(id) === -1) continue; // effective invalidation module.originalCode = null; } } this.watcher.invalidate({ id, event: details.event }); } async run() { if (!this.invalidated) return; this.invalidated = false; const options = { ...this.options, cache: this.cache }; const start = Date.now(); this.watcher.emitter.emit('event', { code: 'BUNDLE_START', input: this.options.input, output: this.outputFiles }); let result = null; try { result = await rollup.rollupInternal(options, this.watcher.emitter); if (this.closed) { return; } this.updateWatchedFiles(result); this.skipWrite || (await Promise.all(this.outputs.map(output => result.write(output)))); this.watcher.emitter.emit('event', { code: 'BUNDLE_END', duration: Date.now() - start, input: this.options.input, output: this.outputFiles, result }); } catch (error) { if (!this.closed) { if (Array.isArray(error.watchFiles)) { for (const id of error.watchFiles) { this.watchFile(id); } } if (error.id) { this.cache.modules = this.cache.modules.filter(module => module.id !== error.id); } } this.watcher.emitter.emit('event', { code: 'ERROR', error, result }); } } updateWatchedFiles(result) { const previouslyWatched = this.watched; this.watched = new Set(); this.watchFiles = result.watchFiles; this.cache = result.cache; for (const id of this.watchFiles) { this.watchFile(id); } for (const module of this.cache.modules) { for (const depId of module.transformDependencies) { this.watchFile(depId, true); } } for (const id of previouslyWatched) { if (!this.watched.has(id)) { this.fileWatcher.unwatch(id); } } } watchFile(id, isTransformDependency = false) { if (!this.filter(id)) return; this.watched.add(id); if (this.outputFiles.some(file => file === id)) { throw new Error('Cannot import the generated bundle'); } // this is necessary to ensure that any 'renamed' files // continue to be watched following an error this.fileWatcher.watch(id, isTransformDependency); } } exports.Task = Task; exports.Watcher = Watcher; //# sourceMappingURL=watch.js.map