source: frontend/node_modules/rollup/dist/es/shared/watch.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 135.2 KB
Line 
1/*
2 @license
3 Rollup.js v2.80.0
4 Sun, 22 Feb 2026 06:16:40 GMT - commit d17ae15336a45c3c59b2a4aacac2b14186035d28
5
6 https://github.com/rollup/rollup
7
8 Released under the MIT License.
9*/
10import require$$0$2, { resolve } from 'path';
11import process$1 from 'process';
12import { ensureArray, warnUnknownOptions, defaultOnWarn, objectifyOptionWithPresets, treeshakePresets, objectifyOption, generatedCodePresets, picomatch as picomatch$2, getAugmentedNamespace, fseventsImporter, createFilter, rollupInternal } from './rollup.js';
13import require$$2$1, { platform } from 'os';
14import require$$0$1 from 'fs';
15import require$$2 from 'util';
16import require$$1 from 'stream';
17import require$$0$3 from 'events';
18import 'perf_hooks';
19import 'crypto';
20
21const commandAliases = {
22 c: 'config',
23 d: 'dir',
24 e: 'external',
25 f: 'format',
26 g: 'globals',
27 h: 'help',
28 i: 'input',
29 m: 'sourcemap',
30 n: 'name',
31 o: 'file',
32 p: 'plugin',
33 v: 'version',
34 w: 'watch'
35};
36function mergeOptions(config, rawCommandOptions = { external: [], globals: undefined }, defaultOnWarnHandler = defaultOnWarn) {
37 const command = getCommandOptions(rawCommandOptions);
38 const inputOptions = mergeInputOptions(config, command, defaultOnWarnHandler);
39 const warn = inputOptions.onwarn;
40 if (command.output) {
41 Object.assign(command, command.output);
42 }
43 const outputOptionsArray = ensureArray(config.output);
44 if (outputOptionsArray.length === 0)
45 outputOptionsArray.push({});
46 const outputOptions = outputOptionsArray.map(singleOutputOptions => mergeOutputOptions(singleOutputOptions, command, warn));
47 warnUnknownOptions(command, Object.keys(inputOptions).concat(Object.keys(outputOptions[0]).filter(option => option !== 'sourcemapPathTransform'), Object.keys(commandAliases), 'config', 'environment', 'plugin', 'silent', 'failAfterWarnings', 'stdin', 'waitForBundleInput', 'configPlugin'), 'CLI flags', warn, /^_$|output$|config/);
48 inputOptions.output = outputOptions;
49 return inputOptions;
50}
51function getCommandOptions(rawCommandOptions) {
52 const external = rawCommandOptions.external && typeof rawCommandOptions.external === 'string'
53 ? rawCommandOptions.external.split(',')
54 : [];
55 return {
56 ...rawCommandOptions,
57 external,
58 globals: typeof rawCommandOptions.globals === 'string'
59 ? rawCommandOptions.globals.split(',').reduce((globals, globalDefinition) => {
60 const [id, variableName] = globalDefinition.split(':');
61 globals[id] = variableName;
62 if (!external.includes(id)) {
63 external.push(id);
64 }
65 return globals;
66 }, Object.create(null))
67 : undefined
68 };
69}
70function mergeInputOptions(config, overrides, defaultOnWarnHandler) {
71 const getOption = (name) => { var _a; return (_a = overrides[name]) !== null && _a !== void 0 ? _a : config[name]; };
72 const inputOptions = {
73 acorn: getOption('acorn'),
74 acornInjectPlugins: config.acornInjectPlugins,
75 cache: config.cache,
76 context: getOption('context'),
77 experimentalCacheExpiry: getOption('experimentalCacheExpiry'),
78 external: getExternal(config, overrides),
79 inlineDynamicImports: getOption('inlineDynamicImports'),
80 input: getOption('input') || [],
81 makeAbsoluteExternalsRelative: getOption('makeAbsoluteExternalsRelative'),
82 manualChunks: getOption('manualChunks'),
83 maxParallelFileOps: getOption('maxParallelFileOps'),
84 maxParallelFileReads: getOption('maxParallelFileReads'),
85 moduleContext: getOption('moduleContext'),
86 onwarn: getOnWarn(config, defaultOnWarnHandler),
87 perf: getOption('perf'),
88 plugins: ensureArray(config.plugins),
89 preserveEntrySignatures: getOption('preserveEntrySignatures'),
90 preserveModules: getOption('preserveModules'),
91 preserveSymlinks: getOption('preserveSymlinks'),
92 shimMissingExports: getOption('shimMissingExports'),
93 strictDeprecations: getOption('strictDeprecations'),
94 treeshake: getObjectOption(config, overrides, 'treeshake', objectifyOptionWithPresets(treeshakePresets, 'treeshake', 'false, true, ')),
95 watch: getWatch(config, overrides)
96 };
97 warnUnknownOptions(config, Object.keys(inputOptions), 'input options', inputOptions.onwarn, /^output$/);
98 return inputOptions;
99}
100const getExternal = (config, overrides) => {
101 const configExternal = config.external;
102 return typeof configExternal === 'function'
103 ? (source, importer, isResolved) => configExternal(source, importer, isResolved) || overrides.external.includes(source)
104 : ensureArray(configExternal).concat(overrides.external);
105};
106const getOnWarn = (config, defaultOnWarnHandler) => config.onwarn
107 ? warning => config.onwarn(warning, defaultOnWarnHandler)
108 : defaultOnWarnHandler;
109const getObjectOption = (config, overrides, name, objectifyValue = objectifyOption) => {
110 const commandOption = normalizeObjectOptionValue(overrides[name], objectifyValue);
111 const configOption = normalizeObjectOptionValue(config[name], objectifyValue);
112 if (commandOption !== undefined) {
113 return commandOption && { ...configOption, ...commandOption };
114 }
115 return configOption;
116};
117const getWatch = (config, overrides) => config.watch !== false && getObjectOption(config, overrides, 'watch');
118const normalizeObjectOptionValue = (optionValue, objectifyValue) => {
119 if (!optionValue) {
120 return optionValue;
121 }
122 if (Array.isArray(optionValue)) {
123 return optionValue.reduce((result, value) => value && result && { ...result, ...objectifyValue(value) }, {});
124 }
125 return objectifyValue(optionValue);
126};
127function mergeOutputOptions(config, overrides, warn) {
128 const getOption = (name) => { var _a; return (_a = overrides[name]) !== null && _a !== void 0 ? _a : config[name]; };
129 const outputOptions = {
130 amd: getObjectOption(config, overrides, 'amd'),
131 assetFileNames: getOption('assetFileNames'),
132 banner: getOption('banner'),
133 chunkFileNames: getOption('chunkFileNames'),
134 compact: getOption('compact'),
135 dir: getOption('dir'),
136 dynamicImportFunction: getOption('dynamicImportFunction'),
137 entryFileNames: getOption('entryFileNames'),
138 esModule: getOption('esModule'),
139 exports: getOption('exports'),
140 extend: getOption('extend'),
141 externalLiveBindings: getOption('externalLiveBindings'),
142 file: getOption('file'),
143 footer: getOption('footer'),
144 format: getOption('format'),
145 freeze: getOption('freeze'),
146 generatedCode: getObjectOption(config, overrides, 'generatedCode', objectifyOptionWithPresets(generatedCodePresets, 'output.generatedCode', '')),
147 globals: getOption('globals'),
148 hoistTransitiveImports: getOption('hoistTransitiveImports'),
149 indent: getOption('indent'),
150 inlineDynamicImports: getOption('inlineDynamicImports'),
151 interop: getOption('interop'),
152 intro: getOption('intro'),
153 manualChunks: getOption('manualChunks'),
154 minifyInternalExports: getOption('minifyInternalExports'),
155 name: getOption('name'),
156 namespaceToStringTag: getOption('namespaceToStringTag'),
157 noConflict: getOption('noConflict'),
158 outro: getOption('outro'),
159 paths: getOption('paths'),
160 plugins: ensureArray(config.plugins),
161 preferConst: getOption('preferConst'),
162 preserveModules: getOption('preserveModules'),
163 preserveModulesRoot: getOption('preserveModulesRoot'),
164 sanitizeFileName: getOption('sanitizeFileName'),
165 sourcemap: getOption('sourcemap'),
166 sourcemapBaseUrl: getOption('sourcemapBaseUrl'),
167 sourcemapExcludeSources: getOption('sourcemapExcludeSources'),
168 sourcemapFile: getOption('sourcemapFile'),
169 sourcemapPathTransform: getOption('sourcemapPathTransform'),
170 strict: getOption('strict'),
171 systemNullSetters: getOption('systemNullSetters'),
172 validate: getOption('validate')
173 };
174 warnUnknownOptions(config, Object.keys(outputOptions), 'output options', warn);
175 return outputOptions;
176}
177
178var chokidar = {};
179
180const fs$3 = require$$0$1;
181const { Readable } = require$$1;
182const sysPath$3 = require$$0$2;
183const { promisify: promisify$3 } = require$$2;
184const picomatch$1 = picomatch$2.exports;
185
186const readdir$1 = promisify$3(fs$3.readdir);
187const stat$3 = promisify$3(fs$3.stat);
188const lstat$2 = promisify$3(fs$3.lstat);
189const realpath$1 = promisify$3(fs$3.realpath);
190
191/**
192 * @typedef {Object} EntryInfo
193 * @property {String} path
194 * @property {String} fullPath
195 * @property {fs.Stats=} stats
196 * @property {fs.Dirent=} dirent
197 * @property {String} basename
198 */
199
200const BANG$2 = '!';
201const RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';
202const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);
203const FILE_TYPE = 'files';
204const DIR_TYPE = 'directories';
205const FILE_DIR_TYPE = 'files_directories';
206const EVERYTHING_TYPE = 'all';
207const ALL_TYPES = [FILE_TYPE, DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE];
208
209const isNormalFlowError = error => NORMAL_FLOW_ERRORS.has(error.code);
210const [maj, min] = process.versions.node.split('.').slice(0, 2).map(n => Number.parseInt(n, 10));
211const wantBigintFsStats = process.platform === 'win32' && (maj > 10 || (maj === 10 && min >= 5));
212
213const normalizeFilter = filter => {
214 if (filter === undefined) return;
215 if (typeof filter === 'function') return filter;
216
217 if (typeof filter === 'string') {
218 const glob = picomatch$1(filter.trim());
219 return entry => glob(entry.basename);
220 }
221
222 if (Array.isArray(filter)) {
223 const positive = [];
224 const negative = [];
225 for (const item of filter) {
226 const trimmed = item.trim();
227 if (trimmed.charAt(0) === BANG$2) {
228 negative.push(picomatch$1(trimmed.slice(1)));
229 } else {
230 positive.push(picomatch$1(trimmed));
231 }
232 }
233
234 if (negative.length > 0) {
235 if (positive.length > 0) {
236 return entry =>
237 positive.some(f => f(entry.basename)) && !negative.some(f => f(entry.basename));
238 }
239 return entry => !negative.some(f => f(entry.basename));
240 }
241 return entry => positive.some(f => f(entry.basename));
242 }
243};
244
245class ReaddirpStream extends Readable {
246 static get defaultOptions() {
247 return {
248 root: '.',
249 /* eslint-disable no-unused-vars */
250 fileFilter: (path) => true,
251 directoryFilter: (path) => true,
252 /* eslint-enable no-unused-vars */
253 type: FILE_TYPE,
254 lstat: false,
255 depth: 2147483648,
256 alwaysStat: false
257 };
258 }
259
260 constructor(options = {}) {
261 super({
262 objectMode: true,
263 autoDestroy: true,
264 highWaterMark: options.highWaterMark || 4096
265 });
266 const opts = { ...ReaddirpStream.defaultOptions, ...options };
267 const { root, type } = opts;
268
269 this._fileFilter = normalizeFilter(opts.fileFilter);
270 this._directoryFilter = normalizeFilter(opts.directoryFilter);
271
272 const statMethod = opts.lstat ? lstat$2 : stat$3;
273 // Use bigint stats if it's windows and stat() supports options (node 10+).
274 if (wantBigintFsStats) {
275 this._stat = path => statMethod(path, { bigint: true });
276 } else {
277 this._stat = statMethod;
278 }
279
280 this._maxDepth = opts.depth;
281 this._wantsDir = [DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type);
282 this._wantsFile = [FILE_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type);
283 this._wantsEverything = type === EVERYTHING_TYPE;
284 this._root = sysPath$3.resolve(root);
285 this._isDirent = ('Dirent' in fs$3) && !opts.alwaysStat;
286 this._statsProp = this._isDirent ? 'dirent' : 'stats';
287 this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };
288
289 // Launch stream with one parent, the root dir.
290 this.parents = [this._exploreDir(root, 1)];
291 this.reading = false;
292 this.parent = undefined;
293 }
294
295 async _read(batch) {
296 if (this.reading) return;
297 this.reading = true;
298
299 try {
300 while (!this.destroyed && batch > 0) {
301 const { path, depth, files = [] } = this.parent || {};
302
303 if (files.length > 0) {
304 const slice = files.splice(0, batch).map(dirent => this._formatEntry(dirent, path));
305 for (const entry of await Promise.all(slice)) {
306 if (this.destroyed) return;
307
308 const entryType = await this._getEntryType(entry);
309 if (entryType === 'directory' && this._directoryFilter(entry)) {
310 if (depth <= this._maxDepth) {
311 this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
312 }
313
314 if (this._wantsDir) {
315 this.push(entry);
316 batch--;
317 }
318 } else if ((entryType === 'file' || this._includeAsFile(entry)) && this._fileFilter(entry)) {
319 if (this._wantsFile) {
320 this.push(entry);
321 batch--;
322 }
323 }
324 }
325 } else {
326 const parent = this.parents.pop();
327 if (!parent) {
328 this.push(null);
329 break;
330 }
331 this.parent = await parent;
332 if (this.destroyed) return;
333 }
334 }
335 } catch (error) {
336 this.destroy(error);
337 } finally {
338 this.reading = false;
339 }
340 }
341
342 async _exploreDir(path, depth) {
343 let files;
344 try {
345 files = await readdir$1(path, this._rdOptions);
346 } catch (error) {
347 this._onError(error);
348 }
349 return { files, depth, path };
350 }
351
352 async _formatEntry(dirent, path) {
353 let entry;
354 try {
355 const basename = this._isDirent ? dirent.name : dirent;
356 const fullPath = sysPath$3.resolve(sysPath$3.join(path, basename));
357 entry = { path: sysPath$3.relative(this._root, fullPath), fullPath, basename };
358 entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
359 } catch (err) {
360 this._onError(err);
361 }
362 return entry;
363 }
364
365 _onError(err) {
366 if (isNormalFlowError(err) && !this.destroyed) {
367 this.emit('warn', err);
368 } else {
369 this.destroy(err);
370 }
371 }
372
373 async _getEntryType(entry) {
374 // entry may be undefined, because a warning or an error were emitted
375 // and the statsProp is undefined
376 const stats = entry && entry[this._statsProp];
377 if (!stats) {
378 return;
379 }
380 if (stats.isFile()) {
381 return 'file';
382 }
383 if (stats.isDirectory()) {
384 return 'directory';
385 }
386 if (stats && stats.isSymbolicLink()) {
387 const full = entry.fullPath;
388 try {
389 const entryRealPath = await realpath$1(full);
390 const entryRealPathStats = await lstat$2(entryRealPath);
391 if (entryRealPathStats.isFile()) {
392 return 'file';
393 }
394 if (entryRealPathStats.isDirectory()) {
395 const len = entryRealPath.length;
396 if (full.startsWith(entryRealPath) && full.substr(len, 1) === sysPath$3.sep) {
397 const recursiveError = new Error(
398 `Circular symlink detected: "${full}" points to "${entryRealPath}"`
399 );
400 recursiveError.code = RECURSIVE_ERROR_CODE;
401 return this._onError(recursiveError);
402 }
403 return 'directory';
404 }
405 } catch (error) {
406 this._onError(error);
407 }
408 }
409 }
410
411 _includeAsFile(entry) {
412 const stats = entry && entry[this._statsProp];
413
414 return stats && this._wantsEverything && !stats.isDirectory();
415 }
416}
417
418/**
419 * @typedef {Object} ReaddirpArguments
420 * @property {Function=} fileFilter
421 * @property {Function=} directoryFilter
422 * @property {String=} type
423 * @property {Number=} depth
424 * @property {String=} root
425 * @property {Boolean=} lstat
426 * @property {Boolean=} bigint
427 */
428
429/**
430 * Main function which ends up calling readdirRec and reads all files and directories in given root recursively.
431 * @param {String} root Root directory
432 * @param {ReaddirpArguments=} options Options to specify root (start directory), filters and recursion depth
433 */
434const readdirp$1 = (root, options = {}) => {
435 let type = options.entryType || options.type;
436 if (type === 'both') type = FILE_DIR_TYPE; // backwards-compatibility
437 if (type) options.type = type;
438 if (!root) {
439 throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');
440 } else if (typeof root !== 'string') {
441 throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');
442 } else if (type && !ALL_TYPES.includes(type)) {
443 throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);
444 }
445
446 options.root = root;
447 return new ReaddirpStream(options);
448};
449
450const readdirpPromise = (root, options = {}) => {
451 return new Promise((resolve, reject) => {
452 const files = [];
453 readdirp$1(root, options)
454 .on('data', entry => files.push(entry))
455 .on('end', () => resolve(files))
456 .on('error', error => reject(error));
457 });
458};
459
460readdirp$1.promise = readdirpPromise;
461readdirp$1.ReaddirpStream = ReaddirpStream;
462readdirp$1.default = readdirp$1;
463
464var readdirp_1 = readdirp$1;
465
466var anymatch$2 = {exports: {}};
467
468/*!
469 * normalize-path <https://github.com/jonschlinkert/normalize-path>
470 *
471 * Copyright (c) 2014-2018, Jon Schlinkert.
472 * Released under the MIT License.
473 */
474
475var normalizePath$2 = function(path, stripTrailing) {
476 if (typeof path !== 'string') {
477 throw new TypeError('expected path to be a string');
478 }
479
480 if (path === '\\' || path === '/') return '/';
481
482 var len = path.length;
483 if (len <= 1) return path;
484
485 // ensure that win32 namespaces has two leading slashes, so that the path is
486 // handled properly by the win32 version of path.parse() after being normalized
487 // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces
488 var prefix = '';
489 if (len > 4 && path[3] === '\\') {
490 var ch = path[2];
491 if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') {
492 path = path.slice(2);
493 prefix = '//';
494 }
495 }
496
497 var segs = path.split(/[/\\]+/);
498 if (stripTrailing !== false && segs[segs.length - 1] === '') {
499 segs.pop();
500 }
501 return prefix + segs.join('/');
502};
503
504Object.defineProperty(anymatch$2.exports, "__esModule", { value: true });
505
506const picomatch = picomatch$2.exports;
507const normalizePath$1 = normalizePath$2;
508
509/**
510 * @typedef {(testString: string) => boolean} AnymatchFn
511 * @typedef {string|RegExp|AnymatchFn} AnymatchPattern
512 * @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher
513 */
514const BANG$1 = '!';
515const DEFAULT_OPTIONS = {returnIndex: false};
516const arrify$1 = (item) => Array.isArray(item) ? item : [item];
517
518/**
519 * @param {AnymatchPattern} matcher
520 * @param {object} options
521 * @returns {AnymatchFn}
522 */
523const createPattern = (matcher, options) => {
524 if (typeof matcher === 'function') {
525 return matcher;
526 }
527 if (typeof matcher === 'string') {
528 const glob = picomatch(matcher, options);
529 return (string) => matcher === string || glob(string);
530 }
531 if (matcher instanceof RegExp) {
532 return (string) => matcher.test(string);
533 }
534 return (string) => false;
535};
536
537/**
538 * @param {Array<Function>} patterns
539 * @param {Array<Function>} negPatterns
540 * @param {String|Array} args
541 * @param {Boolean} returnIndex
542 * @returns {boolean|number}
543 */
544const matchPatterns = (patterns, negPatterns, args, returnIndex) => {
545 const isList = Array.isArray(args);
546 const _path = isList ? args[0] : args;
547 if (!isList && typeof _path !== 'string') {
548 throw new TypeError('anymatch: second argument must be a string: got ' +
549 Object.prototype.toString.call(_path))
550 }
551 const path = normalizePath$1(_path);
552
553 for (let index = 0; index < negPatterns.length; index++) {
554 const nglob = negPatterns[index];
555 if (nglob(path)) {
556 return returnIndex ? -1 : false;
557 }
558 }
559
560 const applied = isList && [path].concat(args.slice(1));
561 for (let index = 0; index < patterns.length; index++) {
562 const pattern = patterns[index];
563 if (isList ? pattern(...applied) : pattern(path)) {
564 return returnIndex ? index : true;
565 }
566 }
567
568 return returnIndex ? -1 : false;
569};
570
571/**
572 * @param {AnymatchMatcher} matchers
573 * @param {Array|string} testString
574 * @param {object} options
575 * @returns {boolean|number|Function}
576 */
577const anymatch$1 = (matchers, testString, options = DEFAULT_OPTIONS) => {
578 if (matchers == null) {
579 throw new TypeError('anymatch: specify first argument');
580 }
581 const opts = typeof options === 'boolean' ? {returnIndex: options} : options;
582 const returnIndex = opts.returnIndex || false;
583
584 // Early cache for matchers.
585 const mtchers = arrify$1(matchers);
586 const negatedGlobs = mtchers
587 .filter(item => typeof item === 'string' && item.charAt(0) === BANG$1)
588 .map(item => item.slice(1))
589 .map(item => picomatch(item, opts));
590 const patterns = mtchers
591 .filter(item => typeof item !== 'string' || (typeof item === 'string' && item.charAt(0) !== BANG$1))
592 .map(matcher => createPattern(matcher, opts));
593
594 if (testString == null) {
595 return (testString, ri = false) => {
596 const returnIndex = typeof ri === 'boolean' ? ri : false;
597 return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
598 }
599 }
600
601 return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
602};
603
604anymatch$1.default = anymatch$1;
605anymatch$2.exports = anymatch$1;
606
607/*!
608 * is-extglob <https://github.com/jonschlinkert/is-extglob>
609 *
610 * Copyright (c) 2014-2016, Jon Schlinkert.
611 * Licensed under the MIT License.
612 */
613
614var isExtglob$1 = function isExtglob(str) {
615 if (typeof str !== 'string' || str === '') {
616 return false;
617 }
618
619 var match;
620 while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) {
621 if (match[2]) return true;
622 str = str.slice(match.index + match[0].length);
623 }
624
625 return false;
626};
627
628/*!
629 * is-glob <https://github.com/jonschlinkert/is-glob>
630 *
631 * Copyright (c) 2014-2017, Jon Schlinkert.
632 * Released under the MIT License.
633 */
634
635var isExtglob = isExtglob$1;
636var chars = { '{': '}', '(': ')', '[': ']'};
637var strictCheck = function(str) {
638 if (str[0] === '!') {
639 return true;
640 }
641 var index = 0;
642 var pipeIndex = -2;
643 var closeSquareIndex = -2;
644 var closeCurlyIndex = -2;
645 var closeParenIndex = -2;
646 var backSlashIndex = -2;
647 while (index < str.length) {
648 if (str[index] === '*') {
649 return true;
650 }
651
652 if (str[index + 1] === '?' && /[\].+)]/.test(str[index])) {
653 return true;
654 }
655
656 if (closeSquareIndex !== -1 && str[index] === '[' && str[index + 1] !== ']') {
657 if (closeSquareIndex < index) {
658 closeSquareIndex = str.indexOf(']', index);
659 }
660 if (closeSquareIndex > index) {
661 if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) {
662 return true;
663 }
664 backSlashIndex = str.indexOf('\\', index);
665 if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) {
666 return true;
667 }
668 }
669 }
670
671 if (closeCurlyIndex !== -1 && str[index] === '{' && str[index + 1] !== '}') {
672 closeCurlyIndex = str.indexOf('}', index);
673 if (closeCurlyIndex > index) {
674 backSlashIndex = str.indexOf('\\', index);
675 if (backSlashIndex === -1 || backSlashIndex > closeCurlyIndex) {
676 return true;
677 }
678 }
679 }
680
681 if (closeParenIndex !== -1 && str[index] === '(' && str[index + 1] === '?' && /[:!=]/.test(str[index + 2]) && str[index + 3] !== ')') {
682 closeParenIndex = str.indexOf(')', index);
683 if (closeParenIndex > index) {
684 backSlashIndex = str.indexOf('\\', index);
685 if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) {
686 return true;
687 }
688 }
689 }
690
691 if (pipeIndex !== -1 && str[index] === '(' && str[index + 1] !== '|') {
692 if (pipeIndex < index) {
693 pipeIndex = str.indexOf('|', index);
694 }
695 if (pipeIndex !== -1 && str[pipeIndex + 1] !== ')') {
696 closeParenIndex = str.indexOf(')', pipeIndex);
697 if (closeParenIndex > pipeIndex) {
698 backSlashIndex = str.indexOf('\\', pipeIndex);
699 if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) {
700 return true;
701 }
702 }
703 }
704 }
705
706 if (str[index] === '\\') {
707 var open = str[index + 1];
708 index += 2;
709 var close = chars[open];
710
711 if (close) {
712 var n = str.indexOf(close, index);
713 if (n !== -1) {
714 index = n + 1;
715 }
716 }
717
718 if (str[index] === '!') {
719 return true;
720 }
721 } else {
722 index++;
723 }
724 }
725 return false;
726};
727
728var relaxedCheck = function(str) {
729 if (str[0] === '!') {
730 return true;
731 }
732 var index = 0;
733 while (index < str.length) {
734 if (/[*?{}()[\]]/.test(str[index])) {
735 return true;
736 }
737
738 if (str[index] === '\\') {
739 var open = str[index + 1];
740 index += 2;
741 var close = chars[open];
742
743 if (close) {
744 var n = str.indexOf(close, index);
745 if (n !== -1) {
746 index = n + 1;
747 }
748 }
749
750 if (str[index] === '!') {
751 return true;
752 }
753 } else {
754 index++;
755 }
756 }
757 return false;
758};
759
760var isGlob$2 = function isGlob(str, options) {
761 if (typeof str !== 'string' || str === '') {
762 return false;
763 }
764
765 if (isExtglob(str)) {
766 return true;
767 }
768
769 var check = strictCheck;
770
771 // optionally relax check
772 if (options && options.strict === false) {
773 check = relaxedCheck;
774 }
775
776 return check(str);
777};
778
779var isGlob$1 = isGlob$2;
780var pathPosixDirname = require$$0$2.posix.dirname;
781var isWin32 = require$$2$1.platform() === 'win32';
782
783var slash = '/';
784var backslash = /\\/g;
785var enclosure = /[\{\[].*[\}\]]$/;
786var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/;
787var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g;
788
789/**
790 * @param {string} str
791 * @param {Object} opts
792 * @param {boolean} [opts.flipBackslashes=true]
793 * @returns {string}
794 */
795var globParent$1 = function globParent(str, opts) {
796 var options = Object.assign({ flipBackslashes: true }, opts);
797
798 // flip windows path separators
799 if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) {
800 str = str.replace(backslash, slash);
801 }
802
803 // special case for strings ending in enclosure containing path separator
804 if (enclosure.test(str)) {
805 str += slash;
806 }
807
808 // preserves full path in case of trailing path separator
809 str += 'a';
810
811 // remove path parts that are globby
812 do {
813 str = pathPosixDirname(str);
814 } while (isGlob$1(str) || globby.test(str));
815
816 // remove escape chars and return result
817 return str.replace(escaped, '$1');
818};
819
820var utils$3 = {};
821
822(function (exports) {
823
824 exports.isInteger = num => {
825 if (typeof num === 'number') {
826 return Number.isInteger(num);
827 }
828 if (typeof num === 'string' && num.trim() !== '') {
829 return Number.isInteger(Number(num));
830 }
831 return false;
832 };
833
834 /**
835 * Find a node of the given type
836 */
837
838 exports.find = (node, type) => node.nodes.find(node => node.type === type);
839
840 /**
841 * Find a node of the given type
842 */
843
844 exports.exceedsLimit = (min, max, step = 1, limit) => {
845 if (limit === false) return false;
846 if (!exports.isInteger(min) || !exports.isInteger(max)) return false;
847 return ((Number(max) - Number(min)) / Number(step)) >= limit;
848 };
849
850 /**
851 * Escape the given node with '\\' before node.value
852 */
853
854 exports.escapeNode = (block, n = 0, type) => {
855 let node = block.nodes[n];
856 if (!node) return;
857
858 if ((type && node.type === type) || node.type === 'open' || node.type === 'close') {
859 if (node.escaped !== true) {
860 node.value = '\\' + node.value;
861 node.escaped = true;
862 }
863 }
864 };
865
866 /**
867 * Returns true if the given brace node should be enclosed in literal braces
868 */
869
870 exports.encloseBrace = node => {
871 if (node.type !== 'brace') return false;
872 if ((node.commas >> 0 + node.ranges >> 0) === 0) {
873 node.invalid = true;
874 return true;
875 }
876 return false;
877 };
878
879 /**
880 * Returns true if a brace node is invalid.
881 */
882
883 exports.isInvalidBrace = block => {
884 if (block.type !== 'brace') return false;
885 if (block.invalid === true || block.dollar) return true;
886 if ((block.commas >> 0 + block.ranges >> 0) === 0) {
887 block.invalid = true;
888 return true;
889 }
890 if (block.open !== true || block.close !== true) {
891 block.invalid = true;
892 return true;
893 }
894 return false;
895 };
896
897 /**
898 * Returns true if a node is an open or close node
899 */
900
901 exports.isOpenOrClose = node => {
902 if (node.type === 'open' || node.type === 'close') {
903 return true;
904 }
905 return node.open === true || node.close === true;
906 };
907
908 /**
909 * Reduce an array of text nodes.
910 */
911
912 exports.reduce = nodes => nodes.reduce((acc, node) => {
913 if (node.type === 'text') acc.push(node.value);
914 if (node.type === 'range') node.type = 'text';
915 return acc;
916 }, []);
917
918 /**
919 * Flatten an array
920 */
921
922 exports.flatten = (...args) => {
923 const result = [];
924 const flat = arr => {
925 for (let i = 0; i < arr.length; i++) {
926 let ele = arr[i];
927 Array.isArray(ele) ? flat(ele) : ele !== void 0 && result.push(ele);
928 }
929 return result;
930 };
931 flat(args);
932 return result;
933 };
934} (utils$3));
935
936const utils$2 = utils$3;
937
938var stringify$4 = (ast, options = {}) => {
939 let stringify = (node, parent = {}) => {
940 let invalidBlock = options.escapeInvalid && utils$2.isInvalidBrace(parent);
941 let invalidNode = node.invalid === true && options.escapeInvalid === true;
942 let output = '';
943
944 if (node.value) {
945 if ((invalidBlock || invalidNode) && utils$2.isOpenOrClose(node)) {
946 return '\\' + node.value;
947 }
948 return node.value;
949 }
950
951 if (node.value) {
952 return node.value;
953 }
954
955 if (node.nodes) {
956 for (let child of node.nodes) {
957 output += stringify(child);
958 }
959 }
960 return output;
961 };
962
963 return stringify(ast);
964};
965
966/*!
967 * is-number <https://github.com/jonschlinkert/is-number>
968 *
969 * Copyright (c) 2014-present, Jon Schlinkert.
970 * Released under the MIT License.
971 */
972
973var isNumber$2 = function(num) {
974 if (typeof num === 'number') {
975 return num - num === 0;
976 }
977 if (typeof num === 'string' && num.trim() !== '') {
978 return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
979 }
980 return false;
981};
982
983/*!
984 * to-regex-range <https://github.com/micromatch/to-regex-range>
985 *
986 * Copyright (c) 2015-present, Jon Schlinkert.
987 * Released under the MIT License.
988 */
989
990const isNumber$1 = isNumber$2;
991
992const toRegexRange$1 = (min, max, options) => {
993 if (isNumber$1(min) === false) {
994 throw new TypeError('toRegexRange: expected the first argument to be a number');
995 }
996
997 if (max === void 0 || min === max) {
998 return String(min);
999 }
1000
1001 if (isNumber$1(max) === false) {
1002 throw new TypeError('toRegexRange: expected the second argument to be a number.');
1003 }
1004
1005 let opts = { relaxZeros: true, ...options };
1006 if (typeof opts.strictZeros === 'boolean') {
1007 opts.relaxZeros = opts.strictZeros === false;
1008 }
1009
1010 let relax = String(opts.relaxZeros);
1011 let shorthand = String(opts.shorthand);
1012 let capture = String(opts.capture);
1013 let wrap = String(opts.wrap);
1014 let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap;
1015
1016 if (toRegexRange$1.cache.hasOwnProperty(cacheKey)) {
1017 return toRegexRange$1.cache[cacheKey].result;
1018 }
1019
1020 let a = Math.min(min, max);
1021 let b = Math.max(min, max);
1022
1023 if (Math.abs(a - b) === 1) {
1024 let result = min + '|' + max;
1025 if (opts.capture) {
1026 return `(${result})`;
1027 }
1028 if (opts.wrap === false) {
1029 return result;
1030 }
1031 return `(?:${result})`;
1032 }
1033
1034 let isPadded = hasPadding(min) || hasPadding(max);
1035 let state = { min, max, a, b };
1036 let positives = [];
1037 let negatives = [];
1038
1039 if (isPadded) {
1040 state.isPadded = isPadded;
1041 state.maxLen = String(state.max).length;
1042 }
1043
1044 if (a < 0) {
1045 let newMin = b < 0 ? Math.abs(b) : 1;
1046 negatives = splitToPatterns(newMin, Math.abs(a), state, opts);
1047 a = state.a = 0;
1048 }
1049
1050 if (b >= 0) {
1051 positives = splitToPatterns(a, b, state, opts);
1052 }
1053
1054 state.negatives = negatives;
1055 state.positives = positives;
1056 state.result = collatePatterns(negatives, positives);
1057
1058 if (opts.capture === true) {
1059 state.result = `(${state.result})`;
1060 } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) {
1061 state.result = `(?:${state.result})`;
1062 }
1063
1064 toRegexRange$1.cache[cacheKey] = state;
1065 return state.result;
1066};
1067
1068function collatePatterns(neg, pos, options) {
1069 let onlyNegative = filterPatterns(neg, pos, '-', false) || [];
1070 let onlyPositive = filterPatterns(pos, neg, '', false) || [];
1071 let intersected = filterPatterns(neg, pos, '-?', true) || [];
1072 let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive);
1073 return subpatterns.join('|');
1074}
1075
1076function splitToRanges(min, max) {
1077 let nines = 1;
1078 let zeros = 1;
1079
1080 let stop = countNines(min, nines);
1081 let stops = new Set([max]);
1082
1083 while (min <= stop && stop <= max) {
1084 stops.add(stop);
1085 nines += 1;
1086 stop = countNines(min, nines);
1087 }
1088
1089 stop = countZeros(max + 1, zeros) - 1;
1090
1091 while (min < stop && stop <= max) {
1092 stops.add(stop);
1093 zeros += 1;
1094 stop = countZeros(max + 1, zeros) - 1;
1095 }
1096
1097 stops = [...stops];
1098 stops.sort(compare);
1099 return stops;
1100}
1101
1102/**
1103 * Convert a range to a regex pattern
1104 * @param {Number} `start`
1105 * @param {Number} `stop`
1106 * @return {String}
1107 */
1108
1109function rangeToPattern(start, stop, options) {
1110 if (start === stop) {
1111 return { pattern: start, count: [], digits: 0 };
1112 }
1113
1114 let zipped = zip(start, stop);
1115 let digits = zipped.length;
1116 let pattern = '';
1117 let count = 0;
1118
1119 for (let i = 0; i < digits; i++) {
1120 let [startDigit, stopDigit] = zipped[i];
1121
1122 if (startDigit === stopDigit) {
1123 pattern += startDigit;
1124
1125 } else if (startDigit !== '0' || stopDigit !== '9') {
1126 pattern += toCharacterClass(startDigit, stopDigit);
1127
1128 } else {
1129 count++;
1130 }
1131 }
1132
1133 if (count) {
1134 pattern += options.shorthand === true ? '\\d' : '[0-9]';
1135 }
1136
1137 return { pattern, count: [count], digits };
1138}
1139
1140function splitToPatterns(min, max, tok, options) {
1141 let ranges = splitToRanges(min, max);
1142 let tokens = [];
1143 let start = min;
1144 let prev;
1145
1146 for (let i = 0; i < ranges.length; i++) {
1147 let max = ranges[i];
1148 let obj = rangeToPattern(String(start), String(max), options);
1149 let zeros = '';
1150
1151 if (!tok.isPadded && prev && prev.pattern === obj.pattern) {
1152 if (prev.count.length > 1) {
1153 prev.count.pop();
1154 }
1155
1156 prev.count.push(obj.count[0]);
1157 prev.string = prev.pattern + toQuantifier(prev.count);
1158 start = max + 1;
1159 continue;
1160 }
1161
1162 if (tok.isPadded) {
1163 zeros = padZeros(max, tok, options);
1164 }
1165
1166 obj.string = zeros + obj.pattern + toQuantifier(obj.count);
1167 tokens.push(obj);
1168 start = max + 1;
1169 prev = obj;
1170 }
1171
1172 return tokens;
1173}
1174
1175function filterPatterns(arr, comparison, prefix, intersection, options) {
1176 let result = [];
1177
1178 for (let ele of arr) {
1179 let { string } = ele;
1180
1181 // only push if _both_ are negative...
1182 if (!intersection && !contains(comparison, 'string', string)) {
1183 result.push(prefix + string);
1184 }
1185
1186 // or _both_ are positive
1187 if (intersection && contains(comparison, 'string', string)) {
1188 result.push(prefix + string);
1189 }
1190 }
1191 return result;
1192}
1193
1194/**
1195 * Zip strings
1196 */
1197
1198function zip(a, b) {
1199 let arr = [];
1200 for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]);
1201 return arr;
1202}
1203
1204function compare(a, b) {
1205 return a > b ? 1 : b > a ? -1 : 0;
1206}
1207
1208function contains(arr, key, val) {
1209 return arr.some(ele => ele[key] === val);
1210}
1211
1212function countNines(min, len) {
1213 return Number(String(min).slice(0, -len) + '9'.repeat(len));
1214}
1215
1216function countZeros(integer, zeros) {
1217 return integer - (integer % Math.pow(10, zeros));
1218}
1219
1220function toQuantifier(digits) {
1221 let [start = 0, stop = ''] = digits;
1222 if (stop || start > 1) {
1223 return `{${start + (stop ? ',' + stop : '')}}`;
1224 }
1225 return '';
1226}
1227
1228function toCharacterClass(a, b, options) {
1229 return `[${a}${(b - a === 1) ? '' : '-'}${b}]`;
1230}
1231
1232function hasPadding(str) {
1233 return /^-?(0+)\d/.test(str);
1234}
1235
1236function padZeros(value, tok, options) {
1237 if (!tok.isPadded) {
1238 return value;
1239 }
1240
1241 let diff = Math.abs(tok.maxLen - String(value).length);
1242 let relax = options.relaxZeros !== false;
1243
1244 switch (diff) {
1245 case 0:
1246 return '';
1247 case 1:
1248 return relax ? '0?' : '0';
1249 case 2:
1250 return relax ? '0{0,2}' : '00';
1251 default: {
1252 return relax ? `0{0,${diff}}` : `0{${diff}}`;
1253 }
1254 }
1255}
1256
1257/**
1258 * Cache
1259 */
1260
1261toRegexRange$1.cache = {};
1262toRegexRange$1.clearCache = () => (toRegexRange$1.cache = {});
1263
1264/**
1265 * Expose `toRegexRange`
1266 */
1267
1268var toRegexRange_1 = toRegexRange$1;
1269
1270/*!
1271 * fill-range <https://github.com/jonschlinkert/fill-range>
1272 *
1273 * Copyright (c) 2014-present, Jon Schlinkert.
1274 * Licensed under the MIT License.
1275 */
1276
1277const util = require$$2;
1278const toRegexRange = toRegexRange_1;
1279
1280const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
1281
1282const transform = toNumber => {
1283 return value => toNumber === true ? Number(value) : String(value);
1284};
1285
1286const isValidValue = value => {
1287 return typeof value === 'number' || (typeof value === 'string' && value !== '');
1288};
1289
1290const isNumber = num => Number.isInteger(+num);
1291
1292const zeros = input => {
1293 let value = `${input}`;
1294 let index = -1;
1295 if (value[0] === '-') value = value.slice(1);
1296 if (value === '0') return false;
1297 while (value[++index] === '0');
1298 return index > 0;
1299};
1300
1301const stringify$3 = (start, end, options) => {
1302 if (typeof start === 'string' || typeof end === 'string') {
1303 return true;
1304 }
1305 return options.stringify === true;
1306};
1307
1308const pad = (input, maxLength, toNumber) => {
1309 if (maxLength > 0) {
1310 let dash = input[0] === '-' ? '-' : '';
1311 if (dash) input = input.slice(1);
1312 input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0'));
1313 }
1314 if (toNumber === false) {
1315 return String(input);
1316 }
1317 return input;
1318};
1319
1320const toMaxLen = (input, maxLength) => {
1321 let negative = input[0] === '-' ? '-' : '';
1322 if (negative) {
1323 input = input.slice(1);
1324 maxLength--;
1325 }
1326 while (input.length < maxLength) input = '0' + input;
1327 return negative ? ('-' + input) : input;
1328};
1329
1330const toSequence = (parts, options) => {
1331 parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
1332 parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
1333
1334 let prefix = options.capture ? '' : '?:';
1335 let positives = '';
1336 let negatives = '';
1337 let result;
1338
1339 if (parts.positives.length) {
1340 positives = parts.positives.join('|');
1341 }
1342
1343 if (parts.negatives.length) {
1344 negatives = `-(${prefix}${parts.negatives.join('|')})`;
1345 }
1346
1347 if (positives && negatives) {
1348 result = `${positives}|${negatives}`;
1349 } else {
1350 result = positives || negatives;
1351 }
1352
1353 if (options.wrap) {
1354 return `(${prefix}${result})`;
1355 }
1356
1357 return result;
1358};
1359
1360const toRange = (a, b, isNumbers, options) => {
1361 if (isNumbers) {
1362 return toRegexRange(a, b, { wrap: false, ...options });
1363 }
1364
1365 let start = String.fromCharCode(a);
1366 if (a === b) return start;
1367
1368 let stop = String.fromCharCode(b);
1369 return `[${start}-${stop}]`;
1370};
1371
1372const toRegex = (start, end, options) => {
1373 if (Array.isArray(start)) {
1374 let wrap = options.wrap === true;
1375 let prefix = options.capture ? '' : '?:';
1376 return wrap ? `(${prefix}${start.join('|')})` : start.join('|');
1377 }
1378 return toRegexRange(start, end, options);
1379};
1380
1381const rangeError = (...args) => {
1382 return new RangeError('Invalid range arguments: ' + util.inspect(...args));
1383};
1384
1385const invalidRange = (start, end, options) => {
1386 if (options.strictRanges === true) throw rangeError([start, end]);
1387 return [];
1388};
1389
1390const invalidStep = (step, options) => {
1391 if (options.strictRanges === true) {
1392 throw new TypeError(`Expected step "${step}" to be a number`);
1393 }
1394 return [];
1395};
1396
1397const fillNumbers = (start, end, step = 1, options = {}) => {
1398 let a = Number(start);
1399 let b = Number(end);
1400
1401 if (!Number.isInteger(a) || !Number.isInteger(b)) {
1402 if (options.strictRanges === true) throw rangeError([start, end]);
1403 return [];
1404 }
1405
1406 // fix negative zero
1407 if (a === 0) a = 0;
1408 if (b === 0) b = 0;
1409
1410 let descending = a > b;
1411 let startString = String(start);
1412 let endString = String(end);
1413 let stepString = String(step);
1414 step = Math.max(Math.abs(step), 1);
1415
1416 let padded = zeros(startString) || zeros(endString) || zeros(stepString);
1417 let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0;
1418 let toNumber = padded === false && stringify$3(start, end, options) === false;
1419 let format = options.transform || transform(toNumber);
1420
1421 if (options.toRegex && step === 1) {
1422 return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options);
1423 }
1424
1425 let parts = { negatives: [], positives: [] };
1426 let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num));
1427 let range = [];
1428 let index = 0;
1429
1430 while (descending ? a >= b : a <= b) {
1431 if (options.toRegex === true && step > 1) {
1432 push(a);
1433 } else {
1434 range.push(pad(format(a, index), maxLen, toNumber));
1435 }
1436 a = descending ? a - step : a + step;
1437 index++;
1438 }
1439
1440 if (options.toRegex === true) {
1441 return step > 1
1442 ? toSequence(parts, options)
1443 : toRegex(range, null, { wrap: false, ...options });
1444 }
1445
1446 return range;
1447};
1448
1449const fillLetters = (start, end, step = 1, options = {}) => {
1450 if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) {
1451 return invalidRange(start, end, options);
1452 }
1453
1454
1455 let format = options.transform || (val => String.fromCharCode(val));
1456 let a = `${start}`.charCodeAt(0);
1457 let b = `${end}`.charCodeAt(0);
1458
1459 let descending = a > b;
1460 let min = Math.min(a, b);
1461 let max = Math.max(a, b);
1462
1463 if (options.toRegex && step === 1) {
1464 return toRange(min, max, false, options);
1465 }
1466
1467 let range = [];
1468 let index = 0;
1469
1470 while (descending ? a >= b : a <= b) {
1471 range.push(format(a, index));
1472 a = descending ? a - step : a + step;
1473 index++;
1474 }
1475
1476 if (options.toRegex === true) {
1477 return toRegex(range, null, { wrap: false, options });
1478 }
1479
1480 return range;
1481};
1482
1483const fill$2 = (start, end, step, options = {}) => {
1484 if (end == null && isValidValue(start)) {
1485 return [start];
1486 }
1487
1488 if (!isValidValue(start) || !isValidValue(end)) {
1489 return invalidRange(start, end, options);
1490 }
1491
1492 if (typeof step === 'function') {
1493 return fill$2(start, end, 1, { transform: step });
1494 }
1495
1496 if (isObject(step)) {
1497 return fill$2(start, end, 0, step);
1498 }
1499
1500 let opts = { ...options };
1501 if (opts.capture === true) opts.wrap = true;
1502 step = step || opts.step || 1;
1503
1504 if (!isNumber(step)) {
1505 if (step != null && !isObject(step)) return invalidStep(step, opts);
1506 return fill$2(start, end, 1, step);
1507 }
1508
1509 if (isNumber(start) && isNumber(end)) {
1510 return fillNumbers(start, end, step, opts);
1511 }
1512
1513 return fillLetters(start, end, Math.max(Math.abs(step), 1), opts);
1514};
1515
1516var fillRange = fill$2;
1517
1518const fill$1 = fillRange;
1519const utils$1 = utils$3;
1520
1521const compile$1 = (ast, options = {}) => {
1522 let walk = (node, parent = {}) => {
1523 let invalidBlock = utils$1.isInvalidBrace(parent);
1524 let invalidNode = node.invalid === true && options.escapeInvalid === true;
1525 let invalid = invalidBlock === true || invalidNode === true;
1526 let prefix = options.escapeInvalid === true ? '\\' : '';
1527 let output = '';
1528
1529 if (node.isOpen === true) {
1530 return prefix + node.value;
1531 }
1532 if (node.isClose === true) {
1533 return prefix + node.value;
1534 }
1535
1536 if (node.type === 'open') {
1537 return invalid ? (prefix + node.value) : '(';
1538 }
1539
1540 if (node.type === 'close') {
1541 return invalid ? (prefix + node.value) : ')';
1542 }
1543
1544 if (node.type === 'comma') {
1545 return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|');
1546 }
1547
1548 if (node.value) {
1549 return node.value;
1550 }
1551
1552 if (node.nodes && node.ranges > 0) {
1553 let args = utils$1.reduce(node.nodes);
1554 let range = fill$1(...args, { ...options, wrap: false, toRegex: true });
1555
1556 if (range.length !== 0) {
1557 return args.length > 1 && range.length > 1 ? `(${range})` : range;
1558 }
1559 }
1560
1561 if (node.nodes) {
1562 for (let child of node.nodes) {
1563 output += walk(child, node);
1564 }
1565 }
1566 return output;
1567 };
1568
1569 return walk(ast);
1570};
1571
1572var compile_1 = compile$1;
1573
1574const fill = fillRange;
1575const stringify$2 = stringify$4;
1576const utils = utils$3;
1577
1578const append = (queue = '', stash = '', enclose = false) => {
1579 let result = [];
1580
1581 queue = [].concat(queue);
1582 stash = [].concat(stash);
1583
1584 if (!stash.length) return queue;
1585 if (!queue.length) {
1586 return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash;
1587 }
1588
1589 for (let item of queue) {
1590 if (Array.isArray(item)) {
1591 for (let value of item) {
1592 result.push(append(value, stash, enclose));
1593 }
1594 } else {
1595 for (let ele of stash) {
1596 if (enclose === true && typeof ele === 'string') ele = `{${ele}}`;
1597 result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele));
1598 }
1599 }
1600 }
1601 return utils.flatten(result);
1602};
1603
1604const expand$1 = (ast, options = {}) => {
1605 let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit;
1606
1607 let walk = (node, parent = {}) => {
1608 node.queue = [];
1609
1610 let p = parent;
1611 let q = parent.queue;
1612
1613 while (p.type !== 'brace' && p.type !== 'root' && p.parent) {
1614 p = p.parent;
1615 q = p.queue;
1616 }
1617
1618 if (node.invalid || node.dollar) {
1619 q.push(append(q.pop(), stringify$2(node, options)));
1620 return;
1621 }
1622
1623 if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) {
1624 q.push(append(q.pop(), ['{}']));
1625 return;
1626 }
1627
1628 if (node.nodes && node.ranges > 0) {
1629 let args = utils.reduce(node.nodes);
1630
1631 if (utils.exceedsLimit(...args, options.step, rangeLimit)) {
1632 throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
1633 }
1634
1635 let range = fill(...args, options);
1636 if (range.length === 0) {
1637 range = stringify$2(node, options);
1638 }
1639
1640 q.push(append(q.pop(), range));
1641 node.nodes = [];
1642 return;
1643 }
1644
1645 let enclose = utils.encloseBrace(node);
1646 let queue = node.queue;
1647 let block = node;
1648
1649 while (block.type !== 'brace' && block.type !== 'root' && block.parent) {
1650 block = block.parent;
1651 queue = block.queue;
1652 }
1653
1654 for (let i = 0; i < node.nodes.length; i++) {
1655 let child = node.nodes[i];
1656
1657 if (child.type === 'comma' && node.type === 'brace') {
1658 if (i === 1) queue.push('');
1659 queue.push('');
1660 continue;
1661 }
1662
1663 if (child.type === 'close') {
1664 q.push(append(q.pop(), queue, enclose));
1665 continue;
1666 }
1667
1668 if (child.value && child.type !== 'open') {
1669 queue.push(append(queue.pop(), child.value));
1670 continue;
1671 }
1672
1673 if (child.nodes) {
1674 walk(child, node);
1675 }
1676 }
1677
1678 return queue;
1679 };
1680
1681 return utils.flatten(walk(ast));
1682};
1683
1684var expand_1 = expand$1;
1685
1686var constants$1 = {
1687 MAX_LENGTH: 1024 * 64,
1688
1689 // Digits
1690 CHAR_0: '0', /* 0 */
1691 CHAR_9: '9', /* 9 */
1692
1693 // Alphabet chars.
1694 CHAR_UPPERCASE_A: 'A', /* A */
1695 CHAR_LOWERCASE_A: 'a', /* a */
1696 CHAR_UPPERCASE_Z: 'Z', /* Z */
1697 CHAR_LOWERCASE_Z: 'z', /* z */
1698
1699 CHAR_LEFT_PARENTHESES: '(', /* ( */
1700 CHAR_RIGHT_PARENTHESES: ')', /* ) */
1701
1702 CHAR_ASTERISK: '*', /* * */
1703
1704 // Non-alphabetic chars.
1705 CHAR_AMPERSAND: '&', /* & */
1706 CHAR_AT: '@', /* @ */
1707 CHAR_BACKSLASH: '\\', /* \ */
1708 CHAR_BACKTICK: '`', /* ` */
1709 CHAR_CARRIAGE_RETURN: '\r', /* \r */
1710 CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */
1711 CHAR_COLON: ':', /* : */
1712 CHAR_COMMA: ',', /* , */
1713 CHAR_DOLLAR: '$', /* . */
1714 CHAR_DOT: '.', /* . */
1715 CHAR_DOUBLE_QUOTE: '"', /* " */
1716 CHAR_EQUAL: '=', /* = */
1717 CHAR_EXCLAMATION_MARK: '!', /* ! */
1718 CHAR_FORM_FEED: '\f', /* \f */
1719 CHAR_FORWARD_SLASH: '/', /* / */
1720 CHAR_HASH: '#', /* # */
1721 CHAR_HYPHEN_MINUS: '-', /* - */
1722 CHAR_LEFT_ANGLE_BRACKET: '<', /* < */
1723 CHAR_LEFT_CURLY_BRACE: '{', /* { */
1724 CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */
1725 CHAR_LINE_FEED: '\n', /* \n */
1726 CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */
1727 CHAR_PERCENT: '%', /* % */
1728 CHAR_PLUS: '+', /* + */
1729 CHAR_QUESTION_MARK: '?', /* ? */
1730 CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */
1731 CHAR_RIGHT_CURLY_BRACE: '}', /* } */
1732 CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */
1733 CHAR_SEMICOLON: ';', /* ; */
1734 CHAR_SINGLE_QUOTE: '\'', /* ' */
1735 CHAR_SPACE: ' ', /* */
1736 CHAR_TAB: '\t', /* \t */
1737 CHAR_UNDERSCORE: '_', /* _ */
1738 CHAR_VERTICAL_LINE: '|', /* | */
1739 CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */
1740};
1741
1742const stringify$1 = stringify$4;
1743
1744/**
1745 * Constants
1746 */
1747
1748const {
1749 MAX_LENGTH,
1750 CHAR_BACKSLASH, /* \ */
1751 CHAR_BACKTICK, /* ` */
1752 CHAR_COMMA, /* , */
1753 CHAR_DOT, /* . */
1754 CHAR_LEFT_PARENTHESES, /* ( */
1755 CHAR_RIGHT_PARENTHESES, /* ) */
1756 CHAR_LEFT_CURLY_BRACE, /* { */
1757 CHAR_RIGHT_CURLY_BRACE, /* } */
1758 CHAR_LEFT_SQUARE_BRACKET, /* [ */
1759 CHAR_RIGHT_SQUARE_BRACKET, /* ] */
1760 CHAR_DOUBLE_QUOTE, /* " */
1761 CHAR_SINGLE_QUOTE, /* ' */
1762 CHAR_NO_BREAK_SPACE,
1763 CHAR_ZERO_WIDTH_NOBREAK_SPACE
1764} = constants$1;
1765
1766/**
1767 * parse
1768 */
1769
1770const parse$1 = (input, options = {}) => {
1771 if (typeof input !== 'string') {
1772 throw new TypeError('Expected a string');
1773 }
1774
1775 let opts = options || {};
1776 let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
1777 if (input.length > max) {
1778 throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`);
1779 }
1780
1781 let ast = { type: 'root', input, nodes: [] };
1782 let stack = [ast];
1783 let block = ast;
1784 let prev = ast;
1785 let brackets = 0;
1786 let length = input.length;
1787 let index = 0;
1788 let depth = 0;
1789 let value;
1790
1791 /**
1792 * Helpers
1793 */
1794
1795 const advance = () => input[index++];
1796 const push = node => {
1797 if (node.type === 'text' && prev.type === 'dot') {
1798 prev.type = 'text';
1799 }
1800
1801 if (prev && prev.type === 'text' && node.type === 'text') {
1802 prev.value += node.value;
1803 return;
1804 }
1805
1806 block.nodes.push(node);
1807 node.parent = block;
1808 node.prev = prev;
1809 prev = node;
1810 return node;
1811 };
1812
1813 push({ type: 'bos' });
1814
1815 while (index < length) {
1816 block = stack[stack.length - 1];
1817 value = advance();
1818
1819 /**
1820 * Invalid chars
1821 */
1822
1823 if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) {
1824 continue;
1825 }
1826
1827 /**
1828 * Escaped chars
1829 */
1830
1831 if (value === CHAR_BACKSLASH) {
1832 push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() });
1833 continue;
1834 }
1835
1836 /**
1837 * Right square bracket (literal): ']'
1838 */
1839
1840 if (value === CHAR_RIGHT_SQUARE_BRACKET) {
1841 push({ type: 'text', value: '\\' + value });
1842 continue;
1843 }
1844
1845 /**
1846 * Left square bracket: '['
1847 */
1848
1849 if (value === CHAR_LEFT_SQUARE_BRACKET) {
1850 brackets++;
1851 let next;
1852
1853 while (index < length && (next = advance())) {
1854 value += next;
1855
1856 if (next === CHAR_LEFT_SQUARE_BRACKET) {
1857 brackets++;
1858 continue;
1859 }
1860
1861 if (next === CHAR_BACKSLASH) {
1862 value += advance();
1863 continue;
1864 }
1865
1866 if (next === CHAR_RIGHT_SQUARE_BRACKET) {
1867 brackets--;
1868
1869 if (brackets === 0) {
1870 break;
1871 }
1872 }
1873 }
1874
1875 push({ type: 'text', value });
1876 continue;
1877 }
1878
1879 /**
1880 * Parentheses
1881 */
1882
1883 if (value === CHAR_LEFT_PARENTHESES) {
1884 block = push({ type: 'paren', nodes: [] });
1885 stack.push(block);
1886 push({ type: 'text', value });
1887 continue;
1888 }
1889
1890 if (value === CHAR_RIGHT_PARENTHESES) {
1891 if (block.type !== 'paren') {
1892 push({ type: 'text', value });
1893 continue;
1894 }
1895 block = stack.pop();
1896 push({ type: 'text', value });
1897 block = stack[stack.length - 1];
1898 continue;
1899 }
1900
1901 /**
1902 * Quotes: '|"|`
1903 */
1904
1905 if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) {
1906 let open = value;
1907 let next;
1908
1909 if (options.keepQuotes !== true) {
1910 value = '';
1911 }
1912
1913 while (index < length && (next = advance())) {
1914 if (next === CHAR_BACKSLASH) {
1915 value += next + advance();
1916 continue;
1917 }
1918
1919 if (next === open) {
1920 if (options.keepQuotes === true) value += next;
1921 break;
1922 }
1923
1924 value += next;
1925 }
1926
1927 push({ type: 'text', value });
1928 continue;
1929 }
1930
1931 /**
1932 * Left curly brace: '{'
1933 */
1934
1935 if (value === CHAR_LEFT_CURLY_BRACE) {
1936 depth++;
1937
1938 let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true;
1939 let brace = {
1940 type: 'brace',
1941 open: true,
1942 close: false,
1943 dollar,
1944 depth,
1945 commas: 0,
1946 ranges: 0,
1947 nodes: []
1948 };
1949
1950 block = push(brace);
1951 stack.push(block);
1952 push({ type: 'open', value });
1953 continue;
1954 }
1955
1956 /**
1957 * Right curly brace: '}'
1958 */
1959
1960 if (value === CHAR_RIGHT_CURLY_BRACE) {
1961 if (block.type !== 'brace') {
1962 push({ type: 'text', value });
1963 continue;
1964 }
1965
1966 let type = 'close';
1967 block = stack.pop();
1968 block.close = true;
1969
1970 push({ type, value });
1971 depth--;
1972
1973 block = stack[stack.length - 1];
1974 continue;
1975 }
1976
1977 /**
1978 * Comma: ','
1979 */
1980
1981 if (value === CHAR_COMMA && depth > 0) {
1982 if (block.ranges > 0) {
1983 block.ranges = 0;
1984 let open = block.nodes.shift();
1985 block.nodes = [open, { type: 'text', value: stringify$1(block) }];
1986 }
1987
1988 push({ type: 'comma', value });
1989 block.commas++;
1990 continue;
1991 }
1992
1993 /**
1994 * Dot: '.'
1995 */
1996
1997 if (value === CHAR_DOT && depth > 0 && block.commas === 0) {
1998 let siblings = block.nodes;
1999
2000 if (depth === 0 || siblings.length === 0) {
2001 push({ type: 'text', value });
2002 continue;
2003 }
2004
2005 if (prev.type === 'dot') {
2006 block.range = [];
2007 prev.value += value;
2008 prev.type = 'range';
2009
2010 if (block.nodes.length !== 3 && block.nodes.length !== 5) {
2011 block.invalid = true;
2012 block.ranges = 0;
2013 prev.type = 'text';
2014 continue;
2015 }
2016
2017 block.ranges++;
2018 block.args = [];
2019 continue;
2020 }
2021
2022 if (prev.type === 'range') {
2023 siblings.pop();
2024
2025 let before = siblings[siblings.length - 1];
2026 before.value += prev.value + value;
2027 prev = before;
2028 block.ranges--;
2029 continue;
2030 }
2031
2032 push({ type: 'dot', value });
2033 continue;
2034 }
2035
2036 /**
2037 * Text
2038 */
2039
2040 push({ type: 'text', value });
2041 }
2042
2043 // Mark imbalanced braces and brackets as invalid
2044 do {
2045 block = stack.pop();
2046
2047 if (block.type !== 'root') {
2048 block.nodes.forEach(node => {
2049 if (!node.nodes) {
2050 if (node.type === 'open') node.isOpen = true;
2051 if (node.type === 'close') node.isClose = true;
2052 if (!node.nodes) node.type = 'text';
2053 node.invalid = true;
2054 }
2055 });
2056
2057 // get the location of the block on parent.nodes (block's siblings)
2058 let parent = stack[stack.length - 1];
2059 let index = parent.nodes.indexOf(block);
2060 // replace the (invalid) block with it's nodes
2061 parent.nodes.splice(index, 1, ...block.nodes);
2062 }
2063 } while (stack.length > 0);
2064
2065 push({ type: 'eos' });
2066 return ast;
2067};
2068
2069var parse_1 = parse$1;
2070
2071const stringify = stringify$4;
2072const compile = compile_1;
2073const expand = expand_1;
2074const parse = parse_1;
2075
2076/**
2077 * Expand the given pattern or create a regex-compatible string.
2078 *
2079 * ```js
2080 * const braces = require('braces');
2081 * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)']
2082 * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c']
2083 * ```
2084 * @param {String} `str`
2085 * @param {Object} `options`
2086 * @return {String}
2087 * @api public
2088 */
2089
2090const braces$1 = (input, options = {}) => {
2091 let output = [];
2092
2093 if (Array.isArray(input)) {
2094 for (let pattern of input) {
2095 let result = braces$1.create(pattern, options);
2096 if (Array.isArray(result)) {
2097 output.push(...result);
2098 } else {
2099 output.push(result);
2100 }
2101 }
2102 } else {
2103 output = [].concat(braces$1.create(input, options));
2104 }
2105
2106 if (options && options.expand === true && options.nodupes === true) {
2107 output = [...new Set(output)];
2108 }
2109 return output;
2110};
2111
2112/**
2113 * Parse the given `str` with the given `options`.
2114 *
2115 * ```js
2116 * // braces.parse(pattern, [, options]);
2117 * const ast = braces.parse('a/{b,c}/d');
2118 * console.log(ast);
2119 * ```
2120 * @param {String} pattern Brace pattern to parse
2121 * @param {Object} options
2122 * @return {Object} Returns an AST
2123 * @api public
2124 */
2125
2126braces$1.parse = (input, options = {}) => parse(input, options);
2127
2128/**
2129 * Creates a braces string from an AST, or an AST node.
2130 *
2131 * ```js
2132 * const braces = require('braces');
2133 * let ast = braces.parse('foo/{a,b}/bar');
2134 * console.log(stringify(ast.nodes[2])); //=> '{a,b}'
2135 * ```
2136 * @param {String} `input` Brace pattern or AST.
2137 * @param {Object} `options`
2138 * @return {Array} Returns an array of expanded values.
2139 * @api public
2140 */
2141
2142braces$1.stringify = (input, options = {}) => {
2143 if (typeof input === 'string') {
2144 return stringify(braces$1.parse(input, options), options);
2145 }
2146 return stringify(input, options);
2147};
2148
2149/**
2150 * Compiles a brace pattern into a regex-compatible, optimized string.
2151 * This method is called by the main [braces](#braces) function by default.
2152 *
2153 * ```js
2154 * const braces = require('braces');
2155 * console.log(braces.compile('a/{b,c}/d'));
2156 * //=> ['a/(b|c)/d']
2157 * ```
2158 * @param {String} `input` Brace pattern or AST.
2159 * @param {Object} `options`
2160 * @return {Array} Returns an array of expanded values.
2161 * @api public
2162 */
2163
2164braces$1.compile = (input, options = {}) => {
2165 if (typeof input === 'string') {
2166 input = braces$1.parse(input, options);
2167 }
2168 return compile(input, options);
2169};
2170
2171/**
2172 * Expands a brace pattern into an array. This method is called by the
2173 * main [braces](#braces) function when `options.expand` is true. Before
2174 * using this method it's recommended that you read the [performance notes](#performance))
2175 * and advantages of using [.compile](#compile) instead.
2176 *
2177 * ```js
2178 * const braces = require('braces');
2179 * console.log(braces.expand('a/{b,c}/d'));
2180 * //=> ['a/b/d', 'a/c/d'];
2181 * ```
2182 * @param {String} `pattern` Brace pattern
2183 * @param {Object} `options`
2184 * @return {Array} Returns an array of expanded values.
2185 * @api public
2186 */
2187
2188braces$1.expand = (input, options = {}) => {
2189 if (typeof input === 'string') {
2190 input = braces$1.parse(input, options);
2191 }
2192
2193 let result = expand(input, options);
2194
2195 // filter out empty strings if specified
2196 if (options.noempty === true) {
2197 result = result.filter(Boolean);
2198 }
2199
2200 // filter out duplicates if specified
2201 if (options.nodupes === true) {
2202 result = [...new Set(result)];
2203 }
2204
2205 return result;
2206};
2207
2208/**
2209 * Processes a brace pattern and returns either an expanded array
2210 * (if `options.expand` is true), a highly optimized regex-compatible string.
2211 * This method is called by the main [braces](#braces) function.
2212 *
2213 * ```js
2214 * const braces = require('braces');
2215 * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}'))
2216 * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)'
2217 * ```
2218 * @param {String} `pattern` Brace pattern
2219 * @param {Object} `options`
2220 * @return {Array} Returns an array of expanded values.
2221 * @api public
2222 */
2223
2224braces$1.create = (input, options = {}) => {
2225 if (input === '' || input.length < 3) {
2226 return [input];
2227 }
2228
2229 return options.expand !== true
2230 ? braces$1.compile(input, options)
2231 : braces$1.expand(input, options);
2232};
2233
2234/**
2235 * Expose "braces"
2236 */
2237
2238var braces_1 = braces$1;
2239
2240var binaryExtensions$1 = {exports: {}};
2241
2242const require$$0 = [
2243 "3dm",
2244 "3ds",
2245 "3g2",
2246 "3gp",
2247 "7z",
2248 "a",
2249 "aac",
2250 "adp",
2251 "ai",
2252 "aif",
2253 "aiff",
2254 "alz",
2255 "ape",
2256 "apk",
2257 "appimage",
2258 "ar",
2259 "arj",
2260 "asf",
2261 "au",
2262 "avi",
2263 "bak",
2264 "baml",
2265 "bh",
2266 "bin",
2267 "bk",
2268 "bmp",
2269 "btif",
2270 "bz2",
2271 "bzip2",
2272 "cab",
2273 "caf",
2274 "cgm",
2275 "class",
2276 "cmx",
2277 "cpio",
2278 "cr2",
2279 "cur",
2280 "dat",
2281 "dcm",
2282 "deb",
2283 "dex",
2284 "djvu",
2285 "dll",
2286 "dmg",
2287 "dng",
2288 "doc",
2289 "docm",
2290 "docx",
2291 "dot",
2292 "dotm",
2293 "dra",
2294 "DS_Store",
2295 "dsk",
2296 "dts",
2297 "dtshd",
2298 "dvb",
2299 "dwg",
2300 "dxf",
2301 "ecelp4800",
2302 "ecelp7470",
2303 "ecelp9600",
2304 "egg",
2305 "eol",
2306 "eot",
2307 "epub",
2308 "exe",
2309 "f4v",
2310 "fbs",
2311 "fh",
2312 "fla",
2313 "flac",
2314 "flatpak",
2315 "fli",
2316 "flv",
2317 "fpx",
2318 "fst",
2319 "fvt",
2320 "g3",
2321 "gh",
2322 "gif",
2323 "graffle",
2324 "gz",
2325 "gzip",
2326 "h261",
2327 "h263",
2328 "h264",
2329 "icns",
2330 "ico",
2331 "ief",
2332 "img",
2333 "ipa",
2334 "iso",
2335 "jar",
2336 "jpeg",
2337 "jpg",
2338 "jpgv",
2339 "jpm",
2340 "jxr",
2341 "key",
2342 "ktx",
2343 "lha",
2344 "lib",
2345 "lvp",
2346 "lz",
2347 "lzh",
2348 "lzma",
2349 "lzo",
2350 "m3u",
2351 "m4a",
2352 "m4v",
2353 "mar",
2354 "mdi",
2355 "mht",
2356 "mid",
2357 "midi",
2358 "mj2",
2359 "mka",
2360 "mkv",
2361 "mmr",
2362 "mng",
2363 "mobi",
2364 "mov",
2365 "movie",
2366 "mp3",
2367 "mp4",
2368 "mp4a",
2369 "mpeg",
2370 "mpg",
2371 "mpga",
2372 "mxu",
2373 "nef",
2374 "npx",
2375 "numbers",
2376 "nupkg",
2377 "o",
2378 "odp",
2379 "ods",
2380 "odt",
2381 "oga",
2382 "ogg",
2383 "ogv",
2384 "otf",
2385 "ott",
2386 "pages",
2387 "pbm",
2388 "pcx",
2389 "pdb",
2390 "pdf",
2391 "pea",
2392 "pgm",
2393 "pic",
2394 "png",
2395 "pnm",
2396 "pot",
2397 "potm",
2398 "potx",
2399 "ppa",
2400 "ppam",
2401 "ppm",
2402 "pps",
2403 "ppsm",
2404 "ppsx",
2405 "ppt",
2406 "pptm",
2407 "pptx",
2408 "psd",
2409 "pya",
2410 "pyc",
2411 "pyo",
2412 "pyv",
2413 "qt",
2414 "rar",
2415 "ras",
2416 "raw",
2417 "resources",
2418 "rgb",
2419 "rip",
2420 "rlc",
2421 "rmf",
2422 "rmvb",
2423 "rpm",
2424 "rtf",
2425 "rz",
2426 "s3m",
2427 "s7z",
2428 "scpt",
2429 "sgi",
2430 "shar",
2431 "snap",
2432 "sil",
2433 "sketch",
2434 "slk",
2435 "smv",
2436 "snk",
2437 "so",
2438 "stl",
2439 "suo",
2440 "sub",
2441 "swf",
2442 "tar",
2443 "tbz",
2444 "tbz2",
2445 "tga",
2446 "tgz",
2447 "thmx",
2448 "tif",
2449 "tiff",
2450 "tlz",
2451 "ttc",
2452 "ttf",
2453 "txz",
2454 "udf",
2455 "uvh",
2456 "uvi",
2457 "uvm",
2458 "uvp",
2459 "uvs",
2460 "uvu",
2461 "viv",
2462 "vob",
2463 "war",
2464 "wav",
2465 "wax",
2466 "wbmp",
2467 "wdp",
2468 "weba",
2469 "webm",
2470 "webp",
2471 "whl",
2472 "wim",
2473 "wm",
2474 "wma",
2475 "wmv",
2476 "wmx",
2477 "woff",
2478 "woff2",
2479 "wrm",
2480 "wvx",
2481 "xbm",
2482 "xif",
2483 "xla",
2484 "xlam",
2485 "xls",
2486 "xlsb",
2487 "xlsm",
2488 "xlsx",
2489 "xlt",
2490 "xltm",
2491 "xltx",
2492 "xm",
2493 "xmind",
2494 "xpi",
2495 "xpm",
2496 "xwd",
2497 "xz",
2498 "z",
2499 "zip",
2500 "zipx"
2501];
2502
2503(function (module) {
2504 module.exports = require$$0;
2505} (binaryExtensions$1));
2506
2507const path = require$$0$2;
2508const binaryExtensions = binaryExtensions$1.exports;
2509
2510const extensions = new Set(binaryExtensions);
2511
2512var isBinaryPath$1 = filePath => extensions.has(path.extname(filePath).slice(1).toLowerCase());
2513
2514var constants = {};
2515
2516(function (exports) {
2517
2518 const {sep} = require$$0$2;
2519 const {platform} = process;
2520 const os = require$$2$1;
2521
2522 exports.EV_ALL = 'all';
2523 exports.EV_READY = 'ready';
2524 exports.EV_ADD = 'add';
2525 exports.EV_CHANGE = 'change';
2526 exports.EV_ADD_DIR = 'addDir';
2527 exports.EV_UNLINK = 'unlink';
2528 exports.EV_UNLINK_DIR = 'unlinkDir';
2529 exports.EV_RAW = 'raw';
2530 exports.EV_ERROR = 'error';
2531
2532 exports.STR_DATA = 'data';
2533 exports.STR_END = 'end';
2534 exports.STR_CLOSE = 'close';
2535
2536 exports.FSEVENT_CREATED = 'created';
2537 exports.FSEVENT_MODIFIED = 'modified';
2538 exports.FSEVENT_DELETED = 'deleted';
2539 exports.FSEVENT_MOVED = 'moved';
2540 exports.FSEVENT_CLONED = 'cloned';
2541 exports.FSEVENT_UNKNOWN = 'unknown';
2542 exports.FSEVENT_TYPE_FILE = 'file';
2543 exports.FSEVENT_TYPE_DIRECTORY = 'directory';
2544 exports.FSEVENT_TYPE_SYMLINK = 'symlink';
2545
2546 exports.KEY_LISTENERS = 'listeners';
2547 exports.KEY_ERR = 'errHandlers';
2548 exports.KEY_RAW = 'rawEmitters';
2549 exports.HANDLER_KEYS = [exports.KEY_LISTENERS, exports.KEY_ERR, exports.KEY_RAW];
2550
2551 exports.DOT_SLASH = `.${sep}`;
2552
2553 exports.BACK_SLASH_RE = /\\/g;
2554 exports.DOUBLE_SLASH_RE = /\/\//;
2555 exports.SLASH_OR_BACK_SLASH_RE = /[/\\]/;
2556 exports.DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
2557 exports.REPLACER_RE = /^\.[/\\]/;
2558
2559 exports.SLASH = '/';
2560 exports.SLASH_SLASH = '//';
2561 exports.BRACE_START = '{';
2562 exports.BANG = '!';
2563 exports.ONE_DOT = '.';
2564 exports.TWO_DOTS = '..';
2565 exports.STAR = '*';
2566 exports.GLOBSTAR = '**';
2567 exports.ROOT_GLOBSTAR = '/**/*';
2568 exports.SLASH_GLOBSTAR = '/**';
2569 exports.DIR_SUFFIX = 'Dir';
2570 exports.ANYMATCH_OPTS = {dot: true};
2571 exports.STRING_TYPE = 'string';
2572 exports.FUNCTION_TYPE = 'function';
2573 exports.EMPTY_STR = '';
2574 exports.EMPTY_FN = () => {};
2575 exports.IDENTITY_FN = val => val;
2576
2577 exports.isWindows = platform === 'win32';
2578 exports.isMacos = platform === 'darwin';
2579 exports.isLinux = platform === 'linux';
2580 exports.isIBMi = os.type() === 'OS400';
2581} (constants));
2582
2583const fs$2 = require$$0$1;
2584const sysPath$2 = require$$0$2;
2585const { promisify: promisify$2 } = require$$2;
2586const isBinaryPath = isBinaryPath$1;
2587const {
2588 isWindows: isWindows$1,
2589 isLinux,
2590 EMPTY_FN: EMPTY_FN$2,
2591 EMPTY_STR: EMPTY_STR$1,
2592 KEY_LISTENERS,
2593 KEY_ERR,
2594 KEY_RAW,
2595 HANDLER_KEYS,
2596 EV_CHANGE: EV_CHANGE$2,
2597 EV_ADD: EV_ADD$2,
2598 EV_ADD_DIR: EV_ADD_DIR$2,
2599 EV_ERROR: EV_ERROR$2,
2600 STR_DATA: STR_DATA$1,
2601 STR_END: STR_END$2,
2602 BRACE_START: BRACE_START$1,
2603 STAR
2604} = constants;
2605
2606const THROTTLE_MODE_WATCH = 'watch';
2607
2608const open = promisify$2(fs$2.open);
2609const stat$2 = promisify$2(fs$2.stat);
2610const lstat$1 = promisify$2(fs$2.lstat);
2611const close = promisify$2(fs$2.close);
2612const fsrealpath = promisify$2(fs$2.realpath);
2613
2614const statMethods$1 = { lstat: lstat$1, stat: stat$2 };
2615
2616// TODO: emit errors properly. Example: EMFILE on Macos.
2617const foreach = (val, fn) => {
2618 if (val instanceof Set) {
2619 val.forEach(fn);
2620 } else {
2621 fn(val);
2622 }
2623};
2624
2625const addAndConvert = (main, prop, item) => {
2626 let container = main[prop];
2627 if (!(container instanceof Set)) {
2628 main[prop] = container = new Set([container]);
2629 }
2630 container.add(item);
2631};
2632
2633const clearItem = cont => key => {
2634 const set = cont[key];
2635 if (set instanceof Set) {
2636 set.clear();
2637 } else {
2638 delete cont[key];
2639 }
2640};
2641
2642const delFromSet = (main, prop, item) => {
2643 const container = main[prop];
2644 if (container instanceof Set) {
2645 container.delete(item);
2646 } else if (container === item) {
2647 delete main[prop];
2648 }
2649};
2650
2651const isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
2652
2653/**
2654 * @typedef {String} Path
2655 */
2656
2657// fs_watch helpers
2658
2659// object to hold per-process fs_watch instances
2660// (may be shared across chokidar FSWatcher instances)
2661
2662/**
2663 * @typedef {Object} FsWatchContainer
2664 * @property {Set} listeners
2665 * @property {Set} errHandlers
2666 * @property {Set} rawEmitters
2667 * @property {fs.FSWatcher=} watcher
2668 * @property {Boolean=} watcherUnusable
2669 */
2670
2671/**
2672 * @type {Map<String,FsWatchContainer>}
2673 */
2674const FsWatchInstances = new Map();
2675
2676/**
2677 * Instantiates the fs_watch interface
2678 * @param {String} path to be watched
2679 * @param {Object} options to be passed to fs_watch
2680 * @param {Function} listener main event handler
2681 * @param {Function} errHandler emits info about errors
2682 * @param {Function} emitRaw emits raw event data
2683 * @returns {fs.FSWatcher} new fsevents instance
2684 */
2685function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
2686 const handleEvent = (rawEvent, evPath) => {
2687 listener(path);
2688 emitRaw(rawEvent, evPath, {watchedPath: path});
2689
2690 // emit based on events occurring for files from a directory's watcher in
2691 // case the file's watcher misses it (and rely on throttling to de-dupe)
2692 if (evPath && path !== evPath) {
2693 fsWatchBroadcast(
2694 sysPath$2.resolve(path, evPath), KEY_LISTENERS, sysPath$2.join(path, evPath)
2695 );
2696 }
2697 };
2698 try {
2699 return fs$2.watch(path, options, handleEvent);
2700 } catch (error) {
2701 errHandler(error);
2702 }
2703}
2704
2705/**
2706 * Helper for passing fs_watch event data to a collection of listeners
2707 * @param {Path} fullPath absolute path bound to fs_watch instance
2708 * @param {String} type listener type
2709 * @param {*=} val1 arguments to be passed to listeners
2710 * @param {*=} val2
2711 * @param {*=} val3
2712 */
2713const fsWatchBroadcast = (fullPath, type, val1, val2, val3) => {
2714 const cont = FsWatchInstances.get(fullPath);
2715 if (!cont) return;
2716 foreach(cont[type], (listener) => {
2717 listener(val1, val2, val3);
2718 });
2719};
2720
2721/**
2722 * Instantiates the fs_watch interface or binds listeners
2723 * to an existing one covering the same file system entry
2724 * @param {String} path
2725 * @param {String} fullPath absolute path
2726 * @param {Object} options to be passed to fs_watch
2727 * @param {Object} handlers container for event listener functions
2728 */
2729const setFsWatchListener = (path, fullPath, options, handlers) => {
2730 const {listener, errHandler, rawEmitter} = handlers;
2731 let cont = FsWatchInstances.get(fullPath);
2732
2733 /** @type {fs.FSWatcher=} */
2734 let watcher;
2735 if (!options.persistent) {
2736 watcher = createFsWatchInstance(
2737 path, options, listener, errHandler, rawEmitter
2738 );
2739 return watcher.close.bind(watcher);
2740 }
2741 if (cont) {
2742 addAndConvert(cont, KEY_LISTENERS, listener);
2743 addAndConvert(cont, KEY_ERR, errHandler);
2744 addAndConvert(cont, KEY_RAW, rawEmitter);
2745 } else {
2746 watcher = createFsWatchInstance(
2747 path,
2748 options,
2749 fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
2750 errHandler, // no need to use broadcast here
2751 fsWatchBroadcast.bind(null, fullPath, KEY_RAW)
2752 );
2753 if (!watcher) return;
2754 watcher.on(EV_ERROR$2, async (error) => {
2755 const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
2756 cont.watcherUnusable = true; // documented since Node 10.4.1
2757 // Workaround for https://github.com/joyent/node/issues/4337
2758 if (isWindows$1 && error.code === 'EPERM') {
2759 try {
2760 const fd = await open(path, 'r');
2761 await close(fd);
2762 broadcastErr(error);
2763 } catch (err) {}
2764 } else {
2765 broadcastErr(error);
2766 }
2767 });
2768 cont = {
2769 listeners: listener,
2770 errHandlers: errHandler,
2771 rawEmitters: rawEmitter,
2772 watcher
2773 };
2774 FsWatchInstances.set(fullPath, cont);
2775 }
2776 // const index = cont.listeners.indexOf(listener);
2777
2778 // removes this instance's listeners and closes the underlying fs_watch
2779 // instance if there are no more listeners left
2780 return () => {
2781 delFromSet(cont, KEY_LISTENERS, listener);
2782 delFromSet(cont, KEY_ERR, errHandler);
2783 delFromSet(cont, KEY_RAW, rawEmitter);
2784 if (isEmptySet(cont.listeners)) {
2785 // Check to protect against issue gh-730.
2786 // if (cont.watcherUnusable) {
2787 cont.watcher.close();
2788 // }
2789 FsWatchInstances.delete(fullPath);
2790 HANDLER_KEYS.forEach(clearItem(cont));
2791 cont.watcher = undefined;
2792 Object.freeze(cont);
2793 }
2794 };
2795};
2796
2797// fs_watchFile helpers
2798
2799// object to hold per-process fs_watchFile instances
2800// (may be shared across chokidar FSWatcher instances)
2801const FsWatchFileInstances = new Map();
2802
2803/**
2804 * Instantiates the fs_watchFile interface or binds listeners
2805 * to an existing one covering the same file system entry
2806 * @param {String} path to be watched
2807 * @param {String} fullPath absolute path
2808 * @param {Object} options options to be passed to fs_watchFile
2809 * @param {Object} handlers container for event listener functions
2810 * @returns {Function} closer
2811 */
2812const setFsWatchFileListener = (path, fullPath, options, handlers) => {
2813 const {listener, rawEmitter} = handlers;
2814 let cont = FsWatchFileInstances.get(fullPath);
2815
2816 const copts = cont && cont.options;
2817 if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
2818 fs$2.unwatchFile(fullPath);
2819 cont = undefined;
2820 }
2821
2822 /* eslint-enable no-unused-vars, prefer-destructuring */
2823
2824 if (cont) {
2825 addAndConvert(cont, KEY_LISTENERS, listener);
2826 addAndConvert(cont, KEY_RAW, rawEmitter);
2827 } else {
2828 // TODO
2829 // listeners.add(listener);
2830 // rawEmitters.add(rawEmitter);
2831 cont = {
2832 listeners: listener,
2833 rawEmitters: rawEmitter,
2834 options,
2835 watcher: fs$2.watchFile(fullPath, options, (curr, prev) => {
2836 foreach(cont.rawEmitters, (rawEmitter) => {
2837 rawEmitter(EV_CHANGE$2, fullPath, {curr, prev});
2838 });
2839 const currmtime = curr.mtimeMs;
2840 if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
2841 foreach(cont.listeners, (listener) => listener(path, curr));
2842 }
2843 })
2844 };
2845 FsWatchFileInstances.set(fullPath, cont);
2846 }
2847 // const index = cont.listeners.indexOf(listener);
2848
2849 // Removes this instance's listeners and closes the underlying fs_watchFile
2850 // instance if there are no more listeners left.
2851 return () => {
2852 delFromSet(cont, KEY_LISTENERS, listener);
2853 delFromSet(cont, KEY_RAW, rawEmitter);
2854 if (isEmptySet(cont.listeners)) {
2855 FsWatchFileInstances.delete(fullPath);
2856 fs$2.unwatchFile(fullPath);
2857 cont.options = cont.watcher = undefined;
2858 Object.freeze(cont);
2859 }
2860 };
2861};
2862
2863/**
2864 * @mixin
2865 */
2866class NodeFsHandler$1 {
2867
2868/**
2869 * @param {import("../index").FSWatcher} fsW
2870 */
2871constructor(fsW) {
2872 this.fsw = fsW;
2873 this._boundHandleError = (error) => fsW._handleError(error);
2874}
2875
2876/**
2877 * Watch file for changes with fs_watchFile or fs_watch.
2878 * @param {String} path to file or dir
2879 * @param {Function} listener on fs change
2880 * @returns {Function} closer for the watcher instance
2881 */
2882_watchWithNodeFs(path, listener) {
2883 const opts = this.fsw.options;
2884 const directory = sysPath$2.dirname(path);
2885 const basename = sysPath$2.basename(path);
2886 const parent = this.fsw._getWatchedDir(directory);
2887 parent.add(basename);
2888 const absolutePath = sysPath$2.resolve(path);
2889 const options = {persistent: opts.persistent};
2890 if (!listener) listener = EMPTY_FN$2;
2891
2892 let closer;
2893 if (opts.usePolling) {
2894 options.interval = opts.enableBinaryInterval && isBinaryPath(basename) ?
2895 opts.binaryInterval : opts.interval;
2896 closer = setFsWatchFileListener(path, absolutePath, options, {
2897 listener,
2898 rawEmitter: this.fsw._emitRaw
2899 });
2900 } else {
2901 closer = setFsWatchListener(path, absolutePath, options, {
2902 listener,
2903 errHandler: this._boundHandleError,
2904 rawEmitter: this.fsw._emitRaw
2905 });
2906 }
2907 return closer;
2908}
2909
2910/**
2911 * Watch a file and emit add event if warranted.
2912 * @param {Path} file Path
2913 * @param {fs.Stats} stats result of fs_stat
2914 * @param {Boolean} initialAdd was the file added at watch instantiation?
2915 * @returns {Function} closer for the watcher instance
2916 */
2917_handleFile(file, stats, initialAdd) {
2918 if (this.fsw.closed) {
2919 return;
2920 }
2921 const dirname = sysPath$2.dirname(file);
2922 const basename = sysPath$2.basename(file);
2923 const parent = this.fsw._getWatchedDir(dirname);
2924 // stats is always present
2925 let prevStats = stats;
2926
2927 // if the file is already being watched, do nothing
2928 if (parent.has(basename)) return;
2929
2930 const listener = async (path, newStats) => {
2931 if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5)) return;
2932 if (!newStats || newStats.mtimeMs === 0) {
2933 try {
2934 const newStats = await stat$2(file);
2935 if (this.fsw.closed) return;
2936 // Check that change event was not fired because of changed only accessTime.
2937 const at = newStats.atimeMs;
2938 const mt = newStats.mtimeMs;
2939 if (!at || at <= mt || mt !== prevStats.mtimeMs) {
2940 this.fsw._emit(EV_CHANGE$2, file, newStats);
2941 }
2942 if (isLinux && prevStats.ino !== newStats.ino) {
2943 this.fsw._closeFile(path);
2944 prevStats = newStats;
2945 this.fsw._addPathCloser(path, this._watchWithNodeFs(file, listener));
2946 } else {
2947 prevStats = newStats;
2948 }
2949 } catch (error) {
2950 // Fix issues where mtime is null but file is still present
2951 this.fsw._remove(dirname, basename);
2952 }
2953 // add is about to be emitted if file not already tracked in parent
2954 } else if (parent.has(basename)) {
2955 // Check that change event was not fired because of changed only accessTime.
2956 const at = newStats.atimeMs;
2957 const mt = newStats.mtimeMs;
2958 if (!at || at <= mt || mt !== prevStats.mtimeMs) {
2959 this.fsw._emit(EV_CHANGE$2, file, newStats);
2960 }
2961 prevStats = newStats;
2962 }
2963 };
2964 // kick off the watcher
2965 const closer = this._watchWithNodeFs(file, listener);
2966
2967 // emit an add event if we're supposed to
2968 if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {
2969 if (!this.fsw._throttle(EV_ADD$2, file, 0)) return;
2970 this.fsw._emit(EV_ADD$2, file, stats);
2971 }
2972
2973 return closer;
2974}
2975
2976/**
2977 * Handle symlinks encountered while reading a dir.
2978 * @param {Object} entry returned by readdirp
2979 * @param {String} directory path of dir being read
2980 * @param {String} path of this item
2981 * @param {String} item basename of this item
2982 * @returns {Promise<Boolean>} true if no more processing is needed for this entry.
2983 */
2984async _handleSymlink(entry, directory, path, item) {
2985 if (this.fsw.closed) {
2986 return;
2987 }
2988 const full = entry.fullPath;
2989 const dir = this.fsw._getWatchedDir(directory);
2990
2991 if (!this.fsw.options.followSymlinks) {
2992 // watch symlink directly (don't follow) and detect changes
2993 this.fsw._incrReadyCount();
2994
2995 let linkPath;
2996 try {
2997 linkPath = await fsrealpath(path);
2998 } catch (e) {
2999 this.fsw._emitReady();
3000 return true;
3001 }
3002
3003 if (this.fsw.closed) return;
3004 if (dir.has(item)) {
3005 if (this.fsw._symlinkPaths.get(full) !== linkPath) {
3006 this.fsw._symlinkPaths.set(full, linkPath);
3007 this.fsw._emit(EV_CHANGE$2, path, entry.stats);
3008 }
3009 } else {
3010 dir.add(item);
3011 this.fsw._symlinkPaths.set(full, linkPath);
3012 this.fsw._emit(EV_ADD$2, path, entry.stats);
3013 }
3014 this.fsw._emitReady();
3015 return true;
3016 }
3017
3018 // don't follow the same symlink more than once
3019 if (this.fsw._symlinkPaths.has(full)) {
3020 return true;
3021 }
3022
3023 this.fsw._symlinkPaths.set(full, true);
3024}
3025
3026_handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
3027 // Normalize the directory name on Windows
3028 directory = sysPath$2.join(directory, EMPTY_STR$1);
3029
3030 if (!wh.hasGlob) {
3031 throttler = this.fsw._throttle('readdir', directory, 1000);
3032 if (!throttler) return;
3033 }
3034
3035 const previous = this.fsw._getWatchedDir(wh.path);
3036 const current = new Set();
3037
3038 let stream = this.fsw._readdirp(directory, {
3039 fileFilter: entry => wh.filterPath(entry),
3040 directoryFilter: entry => wh.filterDir(entry),
3041 depth: 0
3042 }).on(STR_DATA$1, async (entry) => {
3043 if (this.fsw.closed) {
3044 stream = undefined;
3045 return;
3046 }
3047 const item = entry.path;
3048 let path = sysPath$2.join(directory, item);
3049 current.add(item);
3050
3051 if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) {
3052 return;
3053 }
3054
3055 if (this.fsw.closed) {
3056 stream = undefined;
3057 return;
3058 }
3059 // Files that present in current directory snapshot
3060 // but absent in previous are added to watch list and
3061 // emit `add` event.
3062 if (item === target || !target && !previous.has(item)) {
3063 this.fsw._incrReadyCount();
3064
3065 // ensure relativeness of path is preserved in case of watcher reuse
3066 path = sysPath$2.join(dir, sysPath$2.relative(dir, path));
3067
3068 this._addToNodeFs(path, initialAdd, wh, depth + 1);
3069 }
3070 }).on(EV_ERROR$2, this._boundHandleError);
3071
3072 return new Promise(resolve =>
3073 stream.once(STR_END$2, () => {
3074 if (this.fsw.closed) {
3075 stream = undefined;
3076 return;
3077 }
3078 const wasThrottled = throttler ? throttler.clear() : false;
3079
3080 resolve();
3081
3082 // Files that absent in current directory snapshot
3083 // but present in previous emit `remove` event
3084 // and are removed from @watched[directory].
3085 previous.getChildren().filter((item) => {
3086 return item !== directory &&
3087 !current.has(item) &&
3088 // in case of intersecting globs;
3089 // a path may have been filtered out of this readdir, but
3090 // shouldn't be removed because it matches a different glob
3091 (!wh.hasGlob || wh.filterPath({
3092 fullPath: sysPath$2.resolve(directory, item)
3093 }));
3094 }).forEach((item) => {
3095 this.fsw._remove(directory, item);
3096 });
3097
3098 stream = undefined;
3099
3100 // one more time for any missed in case changes came in extremely quickly
3101 if (wasThrottled) this._handleRead(directory, false, wh, target, dir, depth, throttler);
3102 })
3103 );
3104}
3105
3106/**
3107 * Read directory to add / remove files from `@watched` list and re-read it on change.
3108 * @param {String} dir fs path
3109 * @param {fs.Stats} stats
3110 * @param {Boolean} initialAdd
3111 * @param {Number} depth relative to user-supplied path
3112 * @param {String} target child path targeted for watch
3113 * @param {Object} wh Common watch helpers for this path
3114 * @param {String} realpath
3115 * @returns {Promise<Function>} closer for the watcher instance.
3116 */
3117async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {
3118 const parentDir = this.fsw._getWatchedDir(sysPath$2.dirname(dir));
3119 const tracked = parentDir.has(sysPath$2.basename(dir));
3120 if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
3121 if (!wh.hasGlob || wh.globFilter(dir)) this.fsw._emit(EV_ADD_DIR$2, dir, stats);
3122 }
3123
3124 // ensure dir is tracked (harmless if redundant)
3125 parentDir.add(sysPath$2.basename(dir));
3126 this.fsw._getWatchedDir(dir);
3127 let throttler;
3128 let closer;
3129
3130 const oDepth = this.fsw.options.depth;
3131 if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {
3132 if (!target) {
3133 await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
3134 if (this.fsw.closed) return;
3135 }
3136
3137 closer = this._watchWithNodeFs(dir, (dirPath, stats) => {
3138 // if current directory is removed, do nothing
3139 if (stats && stats.mtimeMs === 0) return;
3140
3141 this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
3142 });
3143 }
3144 return closer;
3145}
3146
3147/**
3148 * Handle added file, directory, or glob pattern.
3149 * Delegates call to _handleFile / _handleDir after checks.
3150 * @param {String} path to file or ir
3151 * @param {Boolean} initialAdd was the file added at watch instantiation?
3152 * @param {Object} priorWh depth relative to user-supplied path
3153 * @param {Number} depth Child path actually targeted for watch
3154 * @param {String=} target Child path actually targeted for watch
3155 * @returns {Promise}
3156 */
3157async _addToNodeFs(path, initialAdd, priorWh, depth, target) {
3158 const ready = this.fsw._emitReady;
3159 if (this.fsw._isIgnored(path) || this.fsw.closed) {
3160 ready();
3161 return false;
3162 }
3163
3164 const wh = this.fsw._getWatchHelpers(path, depth);
3165 if (!wh.hasGlob && priorWh) {
3166 wh.hasGlob = priorWh.hasGlob;
3167 wh.globFilter = priorWh.globFilter;
3168 wh.filterPath = entry => priorWh.filterPath(entry);
3169 wh.filterDir = entry => priorWh.filterDir(entry);
3170 }
3171
3172 // evaluate what is at the path we're being asked to watch
3173 try {
3174 const stats = await statMethods$1[wh.statMethod](wh.watchPath);
3175 if (this.fsw.closed) return;
3176 if (this.fsw._isIgnored(wh.watchPath, stats)) {
3177 ready();
3178 return false;
3179 }
3180
3181 const follow = this.fsw.options.followSymlinks && !path.includes(STAR) && !path.includes(BRACE_START$1);
3182 let closer;
3183 if (stats.isDirectory()) {
3184 const absPath = sysPath$2.resolve(path);
3185 const targetPath = follow ? await fsrealpath(path) : path;
3186 if (this.fsw.closed) return;
3187 closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
3188 if (this.fsw.closed) return;
3189 // preserve this symlink's target path
3190 if (absPath !== targetPath && targetPath !== undefined) {
3191 this.fsw._symlinkPaths.set(absPath, targetPath);
3192 }
3193 } else if (stats.isSymbolicLink()) {
3194 const targetPath = follow ? await fsrealpath(path) : path;
3195 if (this.fsw.closed) return;
3196 const parent = sysPath$2.dirname(wh.watchPath);
3197 this.fsw._getWatchedDir(parent).add(wh.watchPath);
3198 this.fsw._emit(EV_ADD$2, wh.watchPath, stats);
3199 closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
3200 if (this.fsw.closed) return;
3201
3202 // preserve this symlink's target path
3203 if (targetPath !== undefined) {
3204 this.fsw._symlinkPaths.set(sysPath$2.resolve(path), targetPath);
3205 }
3206 } else {
3207 closer = this._handleFile(wh.watchPath, stats, initialAdd);
3208 }
3209 ready();
3210
3211 this.fsw._addPathCloser(path, closer);
3212 return false;
3213
3214 } catch (error) {
3215 if (this.fsw._handleError(error)) {
3216 ready();
3217 return path;
3218 }
3219 }
3220}
3221
3222}
3223
3224var nodefsHandler = NodeFsHandler$1;
3225
3226var fseventsHandler = {exports: {}};
3227
3228const require$$3 = /*@__PURE__*/getAugmentedNamespace(fseventsImporter);
3229
3230const fs$1 = require$$0$1;
3231const sysPath$1 = require$$0$2;
3232const { promisify: promisify$1 } = require$$2;
3233
3234let fsevents;
3235try {
3236 fsevents = require$$3.getFsEvents();
3237} catch (error) {
3238 if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error);
3239}
3240
3241if (fsevents) {
3242 // TODO: real check
3243 const mtch = process.version.match(/v(\d+)\.(\d+)/);
3244 if (mtch && mtch[1] && mtch[2]) {
3245 const maj = Number.parseInt(mtch[1], 10);
3246 const min = Number.parseInt(mtch[2], 10);
3247 if (maj === 8 && min < 16) {
3248 fsevents = undefined;
3249 }
3250 }
3251}
3252
3253const {
3254 EV_ADD: EV_ADD$1,
3255 EV_CHANGE: EV_CHANGE$1,
3256 EV_ADD_DIR: EV_ADD_DIR$1,
3257 EV_UNLINK: EV_UNLINK$1,
3258 EV_ERROR: EV_ERROR$1,
3259 STR_DATA,
3260 STR_END: STR_END$1,
3261 FSEVENT_CREATED,
3262 FSEVENT_MODIFIED,
3263 FSEVENT_DELETED,
3264 FSEVENT_MOVED,
3265 // FSEVENT_CLONED,
3266 FSEVENT_UNKNOWN,
3267 FSEVENT_TYPE_FILE,
3268 FSEVENT_TYPE_DIRECTORY,
3269 FSEVENT_TYPE_SYMLINK,
3270
3271 ROOT_GLOBSTAR,
3272 DIR_SUFFIX,
3273 DOT_SLASH,
3274 FUNCTION_TYPE: FUNCTION_TYPE$1,
3275 EMPTY_FN: EMPTY_FN$1,
3276 IDENTITY_FN
3277} = constants;
3278
3279const Depth = (value) => isNaN(value) ? {} : {depth: value};
3280
3281const stat$1 = promisify$1(fs$1.stat);
3282const lstat = promisify$1(fs$1.lstat);
3283const realpath = promisify$1(fs$1.realpath);
3284
3285const statMethods = { stat: stat$1, lstat };
3286
3287/**
3288 * @typedef {String} Path
3289 */
3290
3291/**
3292 * @typedef {Object} FsEventsWatchContainer
3293 * @property {Set<Function>} listeners
3294 * @property {Function} rawEmitter
3295 * @property {{stop: Function}} watcher
3296 */
3297
3298// fsevents instance helper functions
3299/**
3300 * Object to hold per-process fsevents instances (may be shared across chokidar FSWatcher instances)
3301 * @type {Map<Path,FsEventsWatchContainer>}
3302 */
3303const FSEventsWatchers = new Map();
3304
3305// Threshold of duplicate path prefixes at which to start
3306// consolidating going forward
3307const consolidateThreshhold = 10;
3308
3309const wrongEventFlags = new Set([
3310 69888, 70400, 71424, 72704, 73472, 131328, 131840, 262912
3311]);
3312
3313/**
3314 * Instantiates the fsevents interface
3315 * @param {Path} path path to be watched
3316 * @param {Function} callback called when fsevents is bound and ready
3317 * @returns {{stop: Function}} new fsevents instance
3318 */
3319const createFSEventsInstance = (path, callback) => {
3320 const stop = fsevents.watch(path, callback);
3321 return {stop};
3322};
3323
3324/**
3325 * Instantiates the fsevents interface or binds listeners to an existing one covering
3326 * the same file tree.
3327 * @param {Path} path - to be watched
3328 * @param {Path} realPath - real path for symlinks
3329 * @param {Function} listener - called when fsevents emits events
3330 * @param {Function} rawEmitter - passes data to listeners of the 'raw' event
3331 * @returns {Function} closer
3332 */
3333function setFSEventsListener(path, realPath, listener, rawEmitter) {
3334 let watchPath = sysPath$1.extname(realPath) ? sysPath$1.dirname(realPath) : realPath;
3335
3336 const parentPath = sysPath$1.dirname(watchPath);
3337 let cont = FSEventsWatchers.get(watchPath);
3338
3339 // If we've accumulated a substantial number of paths that
3340 // could have been consolidated by watching one directory
3341 // above the current one, create a watcher on the parent
3342 // path instead, so that we do consolidate going forward.
3343 if (couldConsolidate(parentPath)) {
3344 watchPath = parentPath;
3345 }
3346
3347 const resolvedPath = sysPath$1.resolve(path);
3348 const hasSymlink = resolvedPath !== realPath;
3349
3350 const filteredListener = (fullPath, flags, info) => {
3351 if (hasSymlink) fullPath = fullPath.replace(realPath, resolvedPath);
3352 if (
3353 fullPath === resolvedPath ||
3354 !fullPath.indexOf(resolvedPath + sysPath$1.sep)
3355 ) listener(fullPath, flags, info);
3356 };
3357
3358 // check if there is already a watcher on a parent path
3359 // modifies `watchPath` to the parent path when it finds a match
3360 let watchedParent = false;
3361 for (const watchedPath of FSEventsWatchers.keys()) {
3362 if (realPath.indexOf(sysPath$1.resolve(watchedPath) + sysPath$1.sep) === 0) {
3363 watchPath = watchedPath;
3364 cont = FSEventsWatchers.get(watchPath);
3365 watchedParent = true;
3366 break;
3367 }
3368 }
3369
3370 if (cont || watchedParent) {
3371 cont.listeners.add(filteredListener);
3372 } else {
3373 cont = {
3374 listeners: new Set([filteredListener]),
3375 rawEmitter,
3376 watcher: createFSEventsInstance(watchPath, (fullPath, flags) => {
3377 if (!cont.listeners.size) return;
3378 const info = fsevents.getInfo(fullPath, flags);
3379 cont.listeners.forEach(list => {
3380 list(fullPath, flags, info);
3381 });
3382
3383 cont.rawEmitter(info.event, fullPath, info);
3384 })
3385 };
3386 FSEventsWatchers.set(watchPath, cont);
3387 }
3388
3389 // removes this instance's listeners and closes the underlying fsevents
3390 // instance if there are no more listeners left
3391 return () => {
3392 const lst = cont.listeners;
3393
3394 lst.delete(filteredListener);
3395 if (!lst.size) {
3396 FSEventsWatchers.delete(watchPath);
3397 if (cont.watcher) return cont.watcher.stop().then(() => {
3398 cont.rawEmitter = cont.watcher = undefined;
3399 Object.freeze(cont);
3400 });
3401 }
3402 };
3403}
3404
3405// Decide whether or not we should start a new higher-level
3406// parent watcher
3407const couldConsolidate = (path) => {
3408 let count = 0;
3409 for (const watchPath of FSEventsWatchers.keys()) {
3410 if (watchPath.indexOf(path) === 0) {
3411 count++;
3412 if (count >= consolidateThreshhold) {
3413 return true;
3414 }
3415 }
3416 }
3417
3418 return false;
3419};
3420
3421// returns boolean indicating whether fsevents can be used
3422const canUse = () => fsevents && FSEventsWatchers.size < 128;
3423
3424// determines subdirectory traversal levels from root to path
3425const calcDepth = (path, root) => {
3426 let i = 0;
3427 while (!path.indexOf(root) && (path = sysPath$1.dirname(path)) !== root) i++;
3428 return i;
3429};
3430
3431// returns boolean indicating whether the fsevents' event info has the same type
3432// as the one returned by fs.stat
3433const sameTypes = (info, stats) => (
3434 info.type === FSEVENT_TYPE_DIRECTORY && stats.isDirectory() ||
3435 info.type === FSEVENT_TYPE_SYMLINK && stats.isSymbolicLink() ||
3436 info.type === FSEVENT_TYPE_FILE && stats.isFile()
3437);
3438
3439/**
3440 * @mixin
3441 */
3442class FsEventsHandler$1 {
3443
3444/**
3445 * @param {import('../index').FSWatcher} fsw
3446 */
3447constructor(fsw) {
3448 this.fsw = fsw;
3449}
3450checkIgnored(path, stats) {
3451 const ipaths = this.fsw._ignoredPaths;
3452 if (this.fsw._isIgnored(path, stats)) {
3453 ipaths.add(path);
3454 if (stats && stats.isDirectory()) {
3455 ipaths.add(path + ROOT_GLOBSTAR);
3456 }
3457 return true;
3458 }
3459
3460 ipaths.delete(path);
3461 ipaths.delete(path + ROOT_GLOBSTAR);
3462}
3463
3464addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts) {
3465 const event = watchedDir.has(item) ? EV_CHANGE$1 : EV_ADD$1;
3466 this.handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts);
3467}
3468
3469async checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts) {
3470 try {
3471 const stats = await stat$1(path);
3472 if (this.fsw.closed) return;
3473 if (sameTypes(info, stats)) {
3474 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
3475 } else {
3476 this.handleEvent(EV_UNLINK$1, path, fullPath, realPath, parent, watchedDir, item, info, opts);
3477 }
3478 } catch (error) {
3479 if (error.code === 'EACCES') {
3480 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
3481 } else {
3482 this.handleEvent(EV_UNLINK$1, path, fullPath, realPath, parent, watchedDir, item, info, opts);
3483 }
3484 }
3485}
3486
3487handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts) {
3488 if (this.fsw.closed || this.checkIgnored(path)) return;
3489
3490 if (event === EV_UNLINK$1) {
3491 const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY;
3492 // suppress unlink events on never before seen files
3493 if (isDirectory || watchedDir.has(item)) {
3494 this.fsw._remove(parent, item, isDirectory);
3495 }
3496 } else {
3497 if (event === EV_ADD$1) {
3498 // track new directories
3499 if (info.type === FSEVENT_TYPE_DIRECTORY) this.fsw._getWatchedDir(path);
3500
3501 if (info.type === FSEVENT_TYPE_SYMLINK && opts.followSymlinks) {
3502 // push symlinks back to the top of the stack to get handled
3503 const curDepth = opts.depth === undefined ?
3504 undefined : calcDepth(fullPath, realPath) + 1;
3505 return this._addToFsEvents(path, false, true, curDepth);
3506 }
3507
3508 // track new paths
3509 // (other than symlinks being followed, which will be tracked soon)
3510 this.fsw._getWatchedDir(parent).add(item);
3511 }
3512 /**
3513 * @type {'add'|'addDir'|'unlink'|'unlinkDir'}
3514 */
3515 const eventName = info.type === FSEVENT_TYPE_DIRECTORY ? event + DIR_SUFFIX : event;
3516 this.fsw._emit(eventName, path);
3517 if (eventName === EV_ADD_DIR$1) this._addToFsEvents(path, false, true);
3518 }
3519}
3520
3521/**
3522 * Handle symlinks encountered during directory scan
3523 * @param {String} watchPath - file/dir path to be watched with fsevents
3524 * @param {String} realPath - real path (in case of symlinks)
3525 * @param {Function} transform - path transformer
3526 * @param {Function} globFilter - path filter in case a glob pattern was provided
3527 * @returns {Function} closer for the watcher instance
3528*/
3529_watchWithFsEvents(watchPath, realPath, transform, globFilter) {
3530 if (this.fsw.closed || this.fsw._isIgnored(watchPath)) return;
3531 const opts = this.fsw.options;
3532 const watchCallback = async (fullPath, flags, info) => {
3533 if (this.fsw.closed) return;
3534 if (
3535 opts.depth !== undefined &&
3536 calcDepth(fullPath, realPath) > opts.depth
3537 ) return;
3538 const path = transform(sysPath$1.join(
3539 watchPath, sysPath$1.relative(watchPath, fullPath)
3540 ));
3541 if (globFilter && !globFilter(path)) return;
3542 // ensure directories are tracked
3543 const parent = sysPath$1.dirname(path);
3544 const item = sysPath$1.basename(path);
3545 const watchedDir = this.fsw._getWatchedDir(
3546 info.type === FSEVENT_TYPE_DIRECTORY ? path : parent
3547 );
3548
3549 // correct for wrong events emitted
3550 if (wrongEventFlags.has(flags) || info.event === FSEVENT_UNKNOWN) {
3551 if (typeof opts.ignored === FUNCTION_TYPE$1) {
3552 let stats;
3553 try {
3554 stats = await stat$1(path);
3555 } catch (error) {}
3556 if (this.fsw.closed) return;
3557 if (this.checkIgnored(path, stats)) return;
3558 if (sameTypes(info, stats)) {
3559 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
3560 } else {
3561 this.handleEvent(EV_UNLINK$1, path, fullPath, realPath, parent, watchedDir, item, info, opts);
3562 }
3563 } else {
3564 this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts);
3565 }
3566 } else {
3567 switch (info.event) {
3568 case FSEVENT_CREATED:
3569 case FSEVENT_MODIFIED:
3570 return this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
3571 case FSEVENT_DELETED:
3572 case FSEVENT_MOVED:
3573 return this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts);
3574 }
3575 }
3576 };
3577
3578 const closer = setFSEventsListener(
3579 watchPath,
3580 realPath,
3581 watchCallback,
3582 this.fsw._emitRaw
3583 );
3584
3585 this.fsw._emitReady();
3586 return closer;
3587}
3588
3589/**
3590 * Handle symlinks encountered during directory scan
3591 * @param {String} linkPath path to symlink
3592 * @param {String} fullPath absolute path to the symlink
3593 * @param {Function} transform pre-existing path transformer
3594 * @param {Number} curDepth level of subdirectories traversed to where symlink is
3595 * @returns {Promise<void>}
3596 */
3597async _handleFsEventsSymlink(linkPath, fullPath, transform, curDepth) {
3598 // don't follow the same symlink more than once
3599 if (this.fsw.closed || this.fsw._symlinkPaths.has(fullPath)) return;
3600
3601 this.fsw._symlinkPaths.set(fullPath, true);
3602 this.fsw._incrReadyCount();
3603
3604 try {
3605 const linkTarget = await realpath(linkPath);
3606 if (this.fsw.closed) return;
3607 if (this.fsw._isIgnored(linkTarget)) {
3608 return this.fsw._emitReady();
3609 }
3610
3611 this.fsw._incrReadyCount();
3612
3613 // add the linkTarget for watching with a wrapper for transform
3614 // that causes emitted paths to incorporate the link's path
3615 this._addToFsEvents(linkTarget || linkPath, (path) => {
3616 let aliasedPath = linkPath;
3617 if (linkTarget && linkTarget !== DOT_SLASH) {
3618 aliasedPath = path.replace(linkTarget, linkPath);
3619 } else if (path !== DOT_SLASH) {
3620 aliasedPath = sysPath$1.join(linkPath, path);
3621 }
3622 return transform(aliasedPath);
3623 }, false, curDepth);
3624 } catch(error) {
3625 if (this.fsw._handleError(error)) {
3626 return this.fsw._emitReady();
3627 }
3628 }
3629}
3630
3631/**
3632 *
3633 * @param {Path} newPath
3634 * @param {fs.Stats} stats
3635 */
3636emitAdd(newPath, stats, processPath, opts, forceAdd) {
3637 const pp = processPath(newPath);
3638 const isDir = stats.isDirectory();
3639 const dirObj = this.fsw._getWatchedDir(sysPath$1.dirname(pp));
3640 const base = sysPath$1.basename(pp);
3641
3642 // ensure empty dirs get tracked
3643 if (isDir) this.fsw._getWatchedDir(pp);
3644 if (dirObj.has(base)) return;
3645 dirObj.add(base);
3646
3647 if (!opts.ignoreInitial || forceAdd === true) {
3648 this.fsw._emit(isDir ? EV_ADD_DIR$1 : EV_ADD$1, pp, stats);
3649 }
3650}
3651
3652initWatch(realPath, path, wh, processPath) {
3653 if (this.fsw.closed) return;
3654 const closer = this._watchWithFsEvents(
3655 wh.watchPath,
3656 sysPath$1.resolve(realPath || wh.watchPath),
3657 processPath,
3658 wh.globFilter
3659 );
3660 this.fsw._addPathCloser(path, closer);
3661}
3662
3663/**
3664 * Handle added path with fsevents
3665 * @param {String} path file/dir path or glob pattern
3666 * @param {Function|Boolean=} transform converts working path to what the user expects
3667 * @param {Boolean=} forceAdd ensure add is emitted
3668 * @param {Number=} priorDepth Level of subdirectories already traversed.
3669 * @returns {Promise<void>}
3670 */
3671async _addToFsEvents(path, transform, forceAdd, priorDepth) {
3672 if (this.fsw.closed) {
3673 return;
3674 }
3675 const opts = this.fsw.options;
3676 const processPath = typeof transform === FUNCTION_TYPE$1 ? transform : IDENTITY_FN;
3677
3678 const wh = this.fsw._getWatchHelpers(path);
3679
3680 // evaluate what is at the path we're being asked to watch
3681 try {
3682 const stats = await statMethods[wh.statMethod](wh.watchPath);
3683 if (this.fsw.closed) return;
3684 if (this.fsw._isIgnored(wh.watchPath, stats)) {
3685 throw null;
3686 }
3687 if (stats.isDirectory()) {
3688 // emit addDir unless this is a glob parent
3689 if (!wh.globFilter) this.emitAdd(processPath(path), stats, processPath, opts, forceAdd);
3690
3691 // don't recurse further if it would exceed depth setting
3692 if (priorDepth && priorDepth > opts.depth) return;
3693
3694 // scan the contents of the dir
3695 this.fsw._readdirp(wh.watchPath, {
3696 fileFilter: entry => wh.filterPath(entry),
3697 directoryFilter: entry => wh.filterDir(entry),
3698 ...Depth(opts.depth - (priorDepth || 0))
3699 }).on(STR_DATA, (entry) => {
3700 // need to check filterPath on dirs b/c filterDir is less restrictive
3701 if (this.fsw.closed) {
3702 return;
3703 }
3704 if (entry.stats.isDirectory() && !wh.filterPath(entry)) return;
3705
3706 const joinedPath = sysPath$1.join(wh.watchPath, entry.path);
3707 const {fullPath} = entry;
3708
3709 if (wh.followSymlinks && entry.stats.isSymbolicLink()) {
3710 // preserve the current depth here since it can't be derived from
3711 // real paths past the symlink
3712 const curDepth = opts.depth === undefined ?
3713 undefined : calcDepth(joinedPath, sysPath$1.resolve(wh.watchPath)) + 1;
3714
3715 this._handleFsEventsSymlink(joinedPath, fullPath, processPath, curDepth);
3716 } else {
3717 this.emitAdd(joinedPath, entry.stats, processPath, opts, forceAdd);
3718 }
3719 }).on(EV_ERROR$1, EMPTY_FN$1).on(STR_END$1, () => {
3720 this.fsw._emitReady();
3721 });
3722 } else {
3723 this.emitAdd(wh.watchPath, stats, processPath, opts, forceAdd);
3724 this.fsw._emitReady();
3725 }
3726 } catch (error) {
3727 if (!error || this.fsw._handleError(error)) {
3728 // TODO: Strange thing: "should not choke on an ignored watch path" will be failed without 2 ready calls -__-
3729 this.fsw._emitReady();
3730 this.fsw._emitReady();
3731 }
3732 }
3733
3734 if (opts.persistent && forceAdd !== true) {
3735 if (typeof transform === FUNCTION_TYPE$1) {
3736 // realpath has already been resolved
3737 this.initWatch(undefined, path, wh, processPath);
3738 } else {
3739 let realPath;
3740 try {
3741 realPath = await realpath(wh.watchPath);
3742 } catch (e) {}
3743 this.initWatch(realPath, path, wh, processPath);
3744 }
3745 }
3746}
3747
3748}
3749
3750fseventsHandler.exports = FsEventsHandler$1;
3751fseventsHandler.exports.canUse = canUse;
3752
3753const { EventEmitter } = require$$0$3;
3754const fs = require$$0$1;
3755const sysPath = require$$0$2;
3756const { promisify } = require$$2;
3757const readdirp = readdirp_1;
3758const anymatch = anymatch$2.exports.default;
3759const globParent = globParent$1;
3760const isGlob = isGlob$2;
3761const braces = braces_1;
3762const normalizePath = normalizePath$2;
3763
3764const NodeFsHandler = nodefsHandler;
3765const FsEventsHandler = fseventsHandler.exports;
3766const {
3767 EV_ALL,
3768 EV_READY,
3769 EV_ADD,
3770 EV_CHANGE,
3771 EV_UNLINK,
3772 EV_ADD_DIR,
3773 EV_UNLINK_DIR,
3774 EV_RAW,
3775 EV_ERROR,
3776
3777 STR_CLOSE,
3778 STR_END,
3779
3780 BACK_SLASH_RE,
3781 DOUBLE_SLASH_RE,
3782 SLASH_OR_BACK_SLASH_RE,
3783 DOT_RE,
3784 REPLACER_RE,
3785
3786 SLASH,
3787 SLASH_SLASH,
3788 BRACE_START,
3789 BANG,
3790 ONE_DOT,
3791 TWO_DOTS,
3792 GLOBSTAR,
3793 SLASH_GLOBSTAR,
3794 ANYMATCH_OPTS,
3795 STRING_TYPE,
3796 FUNCTION_TYPE,
3797 EMPTY_STR,
3798 EMPTY_FN,
3799
3800 isWindows,
3801 isMacos,
3802 isIBMi
3803} = constants;
3804
3805const stat = promisify(fs.stat);
3806const readdir = promisify(fs.readdir);
3807
3808/**
3809 * @typedef {String} Path
3810 * @typedef {'all'|'add'|'addDir'|'change'|'unlink'|'unlinkDir'|'raw'|'error'|'ready'} EventName
3811 * @typedef {'readdir'|'watch'|'add'|'remove'|'change'} ThrottleType
3812 */
3813
3814/**
3815 *
3816 * @typedef {Object} WatchHelpers
3817 * @property {Boolean} followSymlinks
3818 * @property {'stat'|'lstat'} statMethod
3819 * @property {Path} path
3820 * @property {Path} watchPath
3821 * @property {Function} entryPath
3822 * @property {Boolean} hasGlob
3823 * @property {Object} globFilter
3824 * @property {Function} filterPath
3825 * @property {Function} filterDir
3826 */
3827
3828const arrify = (value = []) => Array.isArray(value) ? value : [value];
3829const flatten = (list, result = []) => {
3830 list.forEach(item => {
3831 if (Array.isArray(item)) {
3832 flatten(item, result);
3833 } else {
3834 result.push(item);
3835 }
3836 });
3837 return result;
3838};
3839
3840const unifyPaths = (paths_) => {
3841 /**
3842 * @type {Array<String>}
3843 */
3844 const paths = flatten(arrify(paths_));
3845 if (!paths.every(p => typeof p === STRING_TYPE)) {
3846 throw new TypeError(`Non-string provided as watch path: ${paths}`);
3847 }
3848 return paths.map(normalizePathToUnix);
3849};
3850
3851// If SLASH_SLASH occurs at the beginning of path, it is not replaced
3852// because "//StoragePC/DrivePool/Movies" is a valid network path
3853const toUnix = (string) => {
3854 let str = string.replace(BACK_SLASH_RE, SLASH);
3855 let prepend = false;
3856 if (str.startsWith(SLASH_SLASH)) {
3857 prepend = true;
3858 }
3859 while (str.match(DOUBLE_SLASH_RE)) {
3860 str = str.replace(DOUBLE_SLASH_RE, SLASH);
3861 }
3862 if (prepend) {
3863 str = SLASH + str;
3864 }
3865 return str;
3866};
3867
3868// Our version of upath.normalize
3869// TODO: this is not equal to path-normalize module - investigate why
3870const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));
3871
3872const normalizeIgnored = (cwd = EMPTY_STR) => (path) => {
3873 if (typeof path !== STRING_TYPE) return path;
3874 return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));
3875};
3876
3877const getAbsolutePath = (path, cwd) => {
3878 if (sysPath.isAbsolute(path)) {
3879 return path;
3880 }
3881 if (path.startsWith(BANG)) {
3882 return BANG + sysPath.join(cwd, path.slice(1));
3883 }
3884 return sysPath.join(cwd, path);
3885};
3886
3887const undef = (opts, key) => opts[key] === undefined;
3888
3889/**
3890 * Directory entry.
3891 * @property {Path} path
3892 * @property {Set<Path>} items
3893 */
3894class DirEntry {
3895 /**
3896 * @param {Path} dir
3897 * @param {Function} removeWatcher
3898 */
3899 constructor(dir, removeWatcher) {
3900 this.path = dir;
3901 this._removeWatcher = removeWatcher;
3902 /** @type {Set<Path>} */
3903 this.items = new Set();
3904 }
3905
3906 add(item) {
3907 const {items} = this;
3908 if (!items) return;
3909 if (item !== ONE_DOT && item !== TWO_DOTS) items.add(item);
3910 }
3911
3912 async remove(item) {
3913 const {items} = this;
3914 if (!items) return;
3915 items.delete(item);
3916 if (items.size > 0) return;
3917
3918 const dir = this.path;
3919 try {
3920 await readdir(dir);
3921 } catch (err) {
3922 if (this._removeWatcher) {
3923 this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));
3924 }
3925 }
3926 }
3927
3928 has(item) {
3929 const {items} = this;
3930 if (!items) return;
3931 return items.has(item);
3932 }
3933
3934 /**
3935 * @returns {Array<String>}
3936 */
3937 getChildren() {
3938 const {items} = this;
3939 if (!items) return;
3940 return [...items.values()];
3941 }
3942
3943 dispose() {
3944 this.items.clear();
3945 delete this.path;
3946 delete this._removeWatcher;
3947 delete this.items;
3948 Object.freeze(this);
3949 }
3950}
3951
3952const STAT_METHOD_F = 'stat';
3953const STAT_METHOD_L = 'lstat';
3954class WatchHelper {
3955 constructor(path, watchPath, follow, fsw) {
3956 this.fsw = fsw;
3957 this.path = path = path.replace(REPLACER_RE, EMPTY_STR);
3958 this.watchPath = watchPath;
3959 this.fullWatchPath = sysPath.resolve(watchPath);
3960 this.hasGlob = watchPath !== path;
3961 /** @type {object|boolean} */
3962 if (path === EMPTY_STR) this.hasGlob = false;
3963 this.globSymlink = this.hasGlob && follow ? undefined : false;
3964 this.globFilter = this.hasGlob ? anymatch(path, undefined, ANYMATCH_OPTS) : false;
3965 this.dirParts = this.getDirParts(path);
3966 this.dirParts.forEach((parts) => {
3967 if (parts.length > 1) parts.pop();
3968 });
3969 this.followSymlinks = follow;
3970 this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
3971 }
3972
3973 checkGlobSymlink(entry) {
3974 // only need to resolve once
3975 // first entry should always have entry.parentDir === EMPTY_STR
3976 if (this.globSymlink === undefined) {
3977 this.globSymlink = entry.fullParentDir === this.fullWatchPath ?
3978 false : {realPath: entry.fullParentDir, linkPath: this.fullWatchPath};
3979 }
3980
3981 if (this.globSymlink) {
3982 return entry.fullPath.replace(this.globSymlink.realPath, this.globSymlink.linkPath);
3983 }
3984
3985 return entry.fullPath;
3986 }
3987
3988 entryPath(entry) {
3989 return sysPath.join(this.watchPath,
3990 sysPath.relative(this.watchPath, this.checkGlobSymlink(entry))
3991 );
3992 }
3993
3994 filterPath(entry) {
3995 const {stats} = entry;
3996 if (stats && stats.isSymbolicLink()) return this.filterDir(entry);
3997 const resolvedPath = this.entryPath(entry);
3998 const matchesGlob = this.hasGlob && typeof this.globFilter === FUNCTION_TYPE ?
3999 this.globFilter(resolvedPath) : true;
4000 return matchesGlob &&
4001 this.fsw._isntIgnored(resolvedPath, stats) &&
4002 this.fsw._hasReadPermissions(stats);
4003 }
4004
4005 getDirParts(path) {
4006 if (!this.hasGlob) return [];
4007 const parts = [];
4008 const expandedPath = path.includes(BRACE_START) ? braces.expand(path) : [path];
4009 expandedPath.forEach((path) => {
4010 parts.push(sysPath.relative(this.watchPath, path).split(SLASH_OR_BACK_SLASH_RE));
4011 });
4012 return parts;
4013 }
4014
4015 filterDir(entry) {
4016 if (this.hasGlob) {
4017 const entryParts = this.getDirParts(this.checkGlobSymlink(entry));
4018 let globstar = false;
4019 this.unmatchedGlob = !this.dirParts.some((parts) => {
4020 return parts.every((part, i) => {
4021 if (part === GLOBSTAR) globstar = true;
4022 return globstar || !entryParts[0][i] || anymatch(part, entryParts[0][i], ANYMATCH_OPTS);
4023 });
4024 });
4025 }
4026 return !this.unmatchedGlob && this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
4027 }
4028}
4029
4030/**
4031 * Watches files & directories for changes. Emitted events:
4032 * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
4033 *
4034 * new FSWatcher()
4035 * .add(directories)
4036 * .on('add', path => log('File', path, 'was added'))
4037 */
4038class FSWatcher extends EventEmitter {
4039// Not indenting methods for history sake; for now.
4040constructor(_opts) {
4041 super();
4042
4043 const opts = {};
4044 if (_opts) Object.assign(opts, _opts); // for frozen objects
4045
4046 /** @type {Map<String, DirEntry>} */
4047 this._watched = new Map();
4048 /** @type {Map<String, Array>} */
4049 this._closers = new Map();
4050 /** @type {Set<String>} */
4051 this._ignoredPaths = new Set();
4052
4053 /** @type {Map<ThrottleType, Map>} */
4054 this._throttled = new Map();
4055
4056 /** @type {Map<Path, String|Boolean>} */
4057 this._symlinkPaths = new Map();
4058
4059 this._streams = new Set();
4060 this.closed = false;
4061
4062 // Set up default options.
4063 if (undef(opts, 'persistent')) opts.persistent = true;
4064 if (undef(opts, 'ignoreInitial')) opts.ignoreInitial = false;
4065 if (undef(opts, 'ignorePermissionErrors')) opts.ignorePermissionErrors = false;
4066 if (undef(opts, 'interval')) opts.interval = 100;
4067 if (undef(opts, 'binaryInterval')) opts.binaryInterval = 300;
4068 if (undef(opts, 'disableGlobbing')) opts.disableGlobbing = false;
4069 opts.enableBinaryInterval = opts.binaryInterval !== opts.interval;
4070
4071 // Enable fsevents on OS X when polling isn't explicitly enabled.
4072 if (undef(opts, 'useFsEvents')) opts.useFsEvents = !opts.usePolling;
4073
4074 // If we can't use fsevents, ensure the options reflect it's disabled.
4075 const canUseFsEvents = FsEventsHandler.canUse();
4076 if (!canUseFsEvents) opts.useFsEvents = false;
4077
4078 // Use polling on Mac if not using fsevents.
4079 // Other platforms use non-polling fs_watch.
4080 if (undef(opts, 'usePolling') && !opts.useFsEvents) {
4081 opts.usePolling = isMacos;
4082 }
4083
4084 // Always default to polling on IBM i because fs.watch() is not available on IBM i.
4085 if(isIBMi) {
4086 opts.usePolling = true;
4087 }
4088
4089 // Global override (useful for end-developers that need to force polling for all
4090 // instances of chokidar, regardless of usage/dependency depth)
4091 const envPoll = process.env.CHOKIDAR_USEPOLLING;
4092 if (envPoll !== undefined) {
4093 const envLower = envPoll.toLowerCase();
4094
4095 if (envLower === 'false' || envLower === '0') {
4096 opts.usePolling = false;
4097 } else if (envLower === 'true' || envLower === '1') {
4098 opts.usePolling = true;
4099 } else {
4100 opts.usePolling = !!envLower;
4101 }
4102 }
4103 const envInterval = process.env.CHOKIDAR_INTERVAL;
4104 if (envInterval) {
4105 opts.interval = Number.parseInt(envInterval, 10);
4106 }
4107
4108 // Editor atomic write normalization enabled by default with fs.watch
4109 if (undef(opts, 'atomic')) opts.atomic = !opts.usePolling && !opts.useFsEvents;
4110 if (opts.atomic) this._pendingUnlinks = new Map();
4111
4112 if (undef(opts, 'followSymlinks')) opts.followSymlinks = true;
4113
4114 if (undef(opts, 'awaitWriteFinish')) opts.awaitWriteFinish = false;
4115 if (opts.awaitWriteFinish === true) opts.awaitWriteFinish = {};
4116 const awf = opts.awaitWriteFinish;
4117 if (awf) {
4118 if (!awf.stabilityThreshold) awf.stabilityThreshold = 2000;
4119 if (!awf.pollInterval) awf.pollInterval = 100;
4120 this._pendingWrites = new Map();
4121 }
4122 if (opts.ignored) opts.ignored = arrify(opts.ignored);
4123
4124 let readyCalls = 0;
4125 this._emitReady = () => {
4126 readyCalls++;
4127 if (readyCalls >= this._readyCount) {
4128 this._emitReady = EMPTY_FN;
4129 this._readyEmitted = true;
4130 // use process.nextTick to allow time for listener to be bound
4131 process.nextTick(() => this.emit(EV_READY));
4132 }
4133 };
4134 this._emitRaw = (...args) => this.emit(EV_RAW, ...args);
4135 this._readyEmitted = false;
4136 this.options = opts;
4137
4138 // Initialize with proper watcher.
4139 if (opts.useFsEvents) {
4140 this._fsEventsHandler = new FsEventsHandler(this);
4141 } else {
4142 this._nodeFsHandler = new NodeFsHandler(this);
4143 }
4144
4145 // You’re frozen when your heart’s not open.
4146 Object.freeze(opts);
4147}
4148
4149// Public methods
4150
4151/**
4152 * Adds paths to be watched on an existing FSWatcher instance
4153 * @param {Path|Array<Path>} paths_
4154 * @param {String=} _origAdd private; for handling non-existent paths to be watched
4155 * @param {Boolean=} _internal private; indicates a non-user add
4156 * @returns {FSWatcher} for chaining
4157 */
4158add(paths_, _origAdd, _internal) {
4159 const {cwd, disableGlobbing} = this.options;
4160 this.closed = false;
4161 let paths = unifyPaths(paths_);
4162 if (cwd) {
4163 paths = paths.map((path) => {
4164 const absPath = getAbsolutePath(path, cwd);
4165
4166 // Check `path` instead of `absPath` because the cwd portion can't be a glob
4167 if (disableGlobbing || !isGlob(path)) {
4168 return absPath;
4169 }
4170 return normalizePath(absPath);
4171 });
4172 }
4173
4174 // set aside negated glob strings
4175 paths = paths.filter((path) => {
4176 if (path.startsWith(BANG)) {
4177 this._ignoredPaths.add(path.slice(1));
4178 return false;
4179 }
4180
4181 // if a path is being added that was previously ignored, stop ignoring it
4182 this._ignoredPaths.delete(path);
4183 this._ignoredPaths.delete(path + SLASH_GLOBSTAR);
4184
4185 // reset the cached userIgnored anymatch fn
4186 // to make ignoredPaths changes effective
4187 this._userIgnored = undefined;
4188
4189 return true;
4190 });
4191
4192 if (this.options.useFsEvents && this._fsEventsHandler) {
4193 if (!this._readyCount) this._readyCount = paths.length;
4194 if (this.options.persistent) this._readyCount *= 2;
4195 paths.forEach((path) => this._fsEventsHandler._addToFsEvents(path));
4196 } else {
4197 if (!this._readyCount) this._readyCount = 0;
4198 this._readyCount += paths.length;
4199 Promise.all(
4200 paths.map(async path => {
4201 const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, 0, 0, _origAdd);
4202 if (res) this._emitReady();
4203 return res;
4204 })
4205 ).then(results => {
4206 if (this.closed) return;
4207 results.filter(item => item).forEach(item => {
4208 this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));
4209 });
4210 });
4211 }
4212
4213 return this;
4214}
4215
4216/**
4217 * Close watchers or start ignoring events from specified paths.
4218 * @param {Path|Array<Path>} paths_ - string or array of strings, file/directory paths and/or globs
4219 * @returns {FSWatcher} for chaining
4220*/
4221unwatch(paths_) {
4222 if (this.closed) return this;
4223 const paths = unifyPaths(paths_);
4224 const {cwd} = this.options;
4225
4226 paths.forEach((path) => {
4227 // convert to absolute path unless relative path already matches
4228 if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {
4229 if (cwd) path = sysPath.join(cwd, path);
4230 path = sysPath.resolve(path);
4231 }
4232
4233 this._closePath(path);
4234
4235 this._ignoredPaths.add(path);
4236 if (this._watched.has(path)) {
4237 this._ignoredPaths.add(path + SLASH_GLOBSTAR);
4238 }
4239
4240 // reset the cached userIgnored anymatch fn
4241 // to make ignoredPaths changes effective
4242 this._userIgnored = undefined;
4243 });
4244
4245 return this;
4246}
4247
4248/**
4249 * Close watchers and remove all listeners from watched paths.
4250 * @returns {Promise<void>}.
4251*/
4252close() {
4253 if (this.closed) return this._closePromise;
4254 this.closed = true;
4255
4256 // Memory management.
4257 this.removeAllListeners();
4258 const closers = [];
4259 this._closers.forEach(closerList => closerList.forEach(closer => {
4260 const promise = closer();
4261 if (promise instanceof Promise) closers.push(promise);
4262 }));
4263 this._streams.forEach(stream => stream.destroy());
4264 this._userIgnored = undefined;
4265 this._readyCount = 0;
4266 this._readyEmitted = false;
4267 this._watched.forEach(dirent => dirent.dispose());
4268 ['closers', 'watched', 'streams', 'symlinkPaths', 'throttled'].forEach(key => {
4269 this[`_${key}`].clear();
4270 });
4271
4272 this._closePromise = closers.length ? Promise.all(closers).then(() => undefined) : Promise.resolve();
4273 return this._closePromise;
4274}
4275
4276/**
4277 * Expose list of watched paths
4278 * @returns {Object} for chaining
4279*/
4280getWatched() {
4281 const watchList = {};
4282 this._watched.forEach((entry, dir) => {
4283 const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;
4284 watchList[key || ONE_DOT] = entry.getChildren().sort();
4285 });
4286 return watchList;
4287}
4288
4289emitWithAll(event, args) {
4290 this.emit(...args);
4291 if (event !== EV_ERROR) this.emit(EV_ALL, ...args);
4292}
4293
4294// Common helpers
4295// --------------
4296
4297/**
4298 * Normalize and emit events.
4299 * Calling _emit DOES NOT MEAN emit() would be called!
4300 * @param {EventName} event Type of event
4301 * @param {Path} path File or directory path
4302 * @param {*=} val1 arguments to be passed with event
4303 * @param {*=} val2
4304 * @param {*=} val3
4305 * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
4306 */
4307async _emit(event, path, val1, val2, val3) {
4308 if (this.closed) return;
4309
4310 const opts = this.options;
4311 if (isWindows) path = sysPath.normalize(path);
4312 if (opts.cwd) path = sysPath.relative(opts.cwd, path);
4313 /** @type Array<any> */
4314 const args = [event, path];
4315 if (val3 !== undefined) args.push(val1, val2, val3);
4316 else if (val2 !== undefined) args.push(val1, val2);
4317 else if (val1 !== undefined) args.push(val1);
4318
4319 const awf = opts.awaitWriteFinish;
4320 let pw;
4321 if (awf && (pw = this._pendingWrites.get(path))) {
4322 pw.lastChange = new Date();
4323 return this;
4324 }
4325
4326 if (opts.atomic) {
4327 if (event === EV_UNLINK) {
4328 this._pendingUnlinks.set(path, args);
4329 setTimeout(() => {
4330 this._pendingUnlinks.forEach((entry, path) => {
4331 this.emit(...entry);
4332 this.emit(EV_ALL, ...entry);
4333 this._pendingUnlinks.delete(path);
4334 });
4335 }, typeof opts.atomic === 'number' ? opts.atomic : 100);
4336 return this;
4337 }
4338 if (event === EV_ADD && this._pendingUnlinks.has(path)) {
4339 event = args[0] = EV_CHANGE;
4340 this._pendingUnlinks.delete(path);
4341 }
4342 }
4343
4344 if (awf && (event === EV_ADD || event === EV_CHANGE) && this._readyEmitted) {
4345 const awfEmit = (err, stats) => {
4346 if (err) {
4347 event = args[0] = EV_ERROR;
4348 args[1] = err;
4349 this.emitWithAll(event, args);
4350 } else if (stats) {
4351 // if stats doesn't exist the file must have been deleted
4352 if (args.length > 2) {
4353 args[2] = stats;
4354 } else {
4355 args.push(stats);
4356 }
4357 this.emitWithAll(event, args);
4358 }
4359 };
4360
4361 this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);
4362 return this;
4363 }
4364
4365 if (event === EV_CHANGE) {
4366 const isThrottled = !this._throttle(EV_CHANGE, path, 50);
4367 if (isThrottled) return this;
4368 }
4369
4370 if (opts.alwaysStat && val1 === undefined &&
4371 (event === EV_ADD || event === EV_ADD_DIR || event === EV_CHANGE)
4372 ) {
4373 const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;
4374 let stats;
4375 try {
4376 stats = await stat(fullPath);
4377 } catch (err) {}
4378 // Suppress event when fs_stat fails, to avoid sending undefined 'stat'
4379 if (!stats || this.closed) return;
4380 args.push(stats);
4381 }
4382 this.emitWithAll(event, args);
4383
4384 return this;
4385}
4386
4387/**
4388 * Common handler for errors
4389 * @param {Error} error
4390 * @returns {Error|Boolean} The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
4391 */
4392_handleError(error) {
4393 const code = error && error.code;
4394 if (error && code !== 'ENOENT' && code !== 'ENOTDIR' &&
4395 (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))
4396 ) {
4397 this.emit(EV_ERROR, error);
4398 }
4399 return error || this.closed;
4400}
4401
4402/**
4403 * Helper utility for throttling
4404 * @param {ThrottleType} actionType type being throttled
4405 * @param {Path} path being acted upon
4406 * @param {Number} timeout duration of time to suppress duplicate actions
4407 * @returns {Object|false} tracking object or false if action should be suppressed
4408 */
4409_throttle(actionType, path, timeout) {
4410 if (!this._throttled.has(actionType)) {
4411 this._throttled.set(actionType, new Map());
4412 }
4413
4414 /** @type {Map<Path, Object>} */
4415 const action = this._throttled.get(actionType);
4416 /** @type {Object} */
4417 const actionPath = action.get(path);
4418
4419 if (actionPath) {
4420 actionPath.count++;
4421 return false;
4422 }
4423
4424 let timeoutObject;
4425 const clear = () => {
4426 const item = action.get(path);
4427 const count = item ? item.count : 0;
4428 action.delete(path);
4429 clearTimeout(timeoutObject);
4430 if (item) clearTimeout(item.timeoutObject);
4431 return count;
4432 };
4433 timeoutObject = setTimeout(clear, timeout);
4434 const thr = {timeoutObject, clear, count: 0};
4435 action.set(path, thr);
4436 return thr;
4437}
4438
4439_incrReadyCount() {
4440 return this._readyCount++;
4441}
4442
4443/**
4444 * Awaits write operation to finish.
4445 * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
4446 * @param {Path} path being acted upon
4447 * @param {Number} threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
4448 * @param {EventName} event
4449 * @param {Function} awfEmit Callback to be called when ready for event to be emitted.
4450 */
4451_awaitWriteFinish(path, threshold, event, awfEmit) {
4452 let timeoutHandler;
4453
4454 let fullPath = path;
4455 if (this.options.cwd && !sysPath.isAbsolute(path)) {
4456 fullPath = sysPath.join(this.options.cwd, path);
4457 }
4458
4459 const now = new Date();
4460
4461 const awaitWriteFinish = (prevStat) => {
4462 fs.stat(fullPath, (err, curStat) => {
4463 if (err || !this._pendingWrites.has(path)) {
4464 if (err && err.code !== 'ENOENT') awfEmit(err);
4465 return;
4466 }
4467
4468 const now = Number(new Date());
4469
4470 if (prevStat && curStat.size !== prevStat.size) {
4471 this._pendingWrites.get(path).lastChange = now;
4472 }
4473 const pw = this._pendingWrites.get(path);
4474 const df = now - pw.lastChange;
4475
4476 if (df >= threshold) {
4477 this._pendingWrites.delete(path);
4478 awfEmit(undefined, curStat);
4479 } else {
4480 timeoutHandler = setTimeout(
4481 awaitWriteFinish,
4482 this.options.awaitWriteFinish.pollInterval,
4483 curStat
4484 );
4485 }
4486 });
4487 };
4488
4489 if (!this._pendingWrites.has(path)) {
4490 this._pendingWrites.set(path, {
4491 lastChange: now,
4492 cancelWait: () => {
4493 this._pendingWrites.delete(path);
4494 clearTimeout(timeoutHandler);
4495 return event;
4496 }
4497 });
4498 timeoutHandler = setTimeout(
4499 awaitWriteFinish,
4500 this.options.awaitWriteFinish.pollInterval
4501 );
4502 }
4503}
4504
4505_getGlobIgnored() {
4506 return [...this._ignoredPaths.values()];
4507}
4508
4509/**
4510 * Determines whether user has asked to ignore this path.
4511 * @param {Path} path filepath or dir
4512 * @param {fs.Stats=} stats result of fs.stat
4513 * @returns {Boolean}
4514 */
4515_isIgnored(path, stats) {
4516 if (this.options.atomic && DOT_RE.test(path)) return true;
4517 if (!this._userIgnored) {
4518 const {cwd} = this.options;
4519 const ign = this.options.ignored;
4520
4521 const ignored = ign && ign.map(normalizeIgnored(cwd));
4522 const paths = arrify(ignored)
4523 .filter((path) => typeof path === STRING_TYPE && !isGlob(path))
4524 .map((path) => path + SLASH_GLOBSTAR);
4525 const list = this._getGlobIgnored().map(normalizeIgnored(cwd)).concat(ignored, paths);
4526 this._userIgnored = anymatch(list, undefined, ANYMATCH_OPTS);
4527 }
4528
4529 return this._userIgnored([path, stats]);
4530}
4531
4532_isntIgnored(path, stat) {
4533 return !this._isIgnored(path, stat);
4534}
4535
4536/**
4537 * Provides a set of common helpers and properties relating to symlink and glob handling.
4538 * @param {Path} path file, directory, or glob pattern being watched
4539 * @param {Number=} depth at any depth > 0, this isn't a glob
4540 * @returns {WatchHelper} object containing helpers for this path
4541 */
4542_getWatchHelpers(path, depth) {
4543 const watchPath = depth || this.options.disableGlobbing || !isGlob(path) ? path : globParent(path);
4544 const follow = this.options.followSymlinks;
4545
4546 return new WatchHelper(path, watchPath, follow, this);
4547}
4548
4549// Directory helpers
4550// -----------------
4551
4552/**
4553 * Provides directory tracking objects
4554 * @param {String} directory path of the directory
4555 * @returns {DirEntry} the directory's tracking object
4556 */
4557_getWatchedDir(directory) {
4558 if (!this._boundRemove) this._boundRemove = this._remove.bind(this);
4559 const dir = sysPath.resolve(directory);
4560 if (!this._watched.has(dir)) this._watched.set(dir, new DirEntry(dir, this._boundRemove));
4561 return this._watched.get(dir);
4562}
4563
4564// File helpers
4565// ------------
4566
4567/**
4568 * Check for read permissions.
4569 * Based on this answer on SO: https://stackoverflow.com/a/11781404/1358405
4570 * @param {fs.Stats} stats - object, result of fs_stat
4571 * @returns {Boolean} indicates whether the file can be read
4572*/
4573_hasReadPermissions(stats) {
4574 if (this.options.ignorePermissionErrors) return true;
4575
4576 // stats.mode may be bigint
4577 const md = stats && Number.parseInt(stats.mode, 10);
4578 const st = md & 0o777;
4579 const it = Number.parseInt(st.toString(8)[0], 10);
4580 return Boolean(4 & it);
4581}
4582
4583/**
4584 * Handles emitting unlink events for
4585 * files and directories, and via recursion, for
4586 * files and directories within directories that are unlinked
4587 * @param {String} directory within which the following item is located
4588 * @param {String} item base path of item/directory
4589 * @returns {void}
4590*/
4591_remove(directory, item, isDirectory) {
4592 // if what is being deleted is a directory, get that directory's paths
4593 // for recursive deleting and cleaning of watched object
4594 // if it is not a directory, nestedDirectoryChildren will be empty array
4595 const path = sysPath.join(directory, item);
4596 const fullPath = sysPath.resolve(path);
4597 isDirectory = isDirectory != null
4598 ? isDirectory
4599 : this._watched.has(path) || this._watched.has(fullPath);
4600
4601 // prevent duplicate handling in case of arriving here nearly simultaneously
4602 // via multiple paths (such as _handleFile and _handleDir)
4603 if (!this._throttle('remove', path, 100)) return;
4604
4605 // if the only watched file is removed, watch for its return
4606 if (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) {
4607 this.add(directory, item, true);
4608 }
4609
4610 // This will create a new entry in the watched object in either case
4611 // so we got to do the directory check beforehand
4612 const wp = this._getWatchedDir(path);
4613 const nestedDirectoryChildren = wp.getChildren();
4614
4615 // Recursively remove children directories / files.
4616 nestedDirectoryChildren.forEach(nested => this._remove(path, nested));
4617
4618 // Check if item was on the watched list and remove it
4619 const parent = this._getWatchedDir(directory);
4620 const wasTracked = parent.has(item);
4621 parent.remove(item);
4622
4623 // Fixes issue #1042 -> Relative paths were detected and added as symlinks
4624 // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),
4625 // but never removed from the map in case the path was deleted.
4626 // This leads to an incorrect state if the path was recreated:
4627 // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553
4628 if (this._symlinkPaths.has(fullPath)) {
4629 this._symlinkPaths.delete(fullPath);
4630 }
4631
4632 // If we wait for this file to be fully written, cancel the wait.
4633 let relPath = path;
4634 if (this.options.cwd) relPath = sysPath.relative(this.options.cwd, path);
4635 if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
4636 const event = this._pendingWrites.get(relPath).cancelWait();
4637 if (event === EV_ADD) return;
4638 }
4639
4640 // The Entry will either be a directory that just got removed
4641 // or a bogus entry to a file, in either case we have to remove it
4642 this._watched.delete(path);
4643 this._watched.delete(fullPath);
4644 const eventName = isDirectory ? EV_UNLINK_DIR : EV_UNLINK;
4645 if (wasTracked && !this._isIgnored(path)) this._emit(eventName, path);
4646
4647 // Avoid conflicts if we later create another file with the same name
4648 if (!this.options.useFsEvents) {
4649 this._closePath(path);
4650 }
4651}
4652
4653/**
4654 * Closes all watchers for a path
4655 * @param {Path} path
4656 */
4657_closePath(path) {
4658 this._closeFile(path);
4659 const dir = sysPath.dirname(path);
4660 this._getWatchedDir(dir).remove(sysPath.basename(path));
4661}
4662
4663/**
4664 * Closes only file-specific watchers
4665 * @param {Path} path
4666 */
4667_closeFile(path) {
4668 const closers = this._closers.get(path);
4669 if (!closers) return;
4670 closers.forEach(closer => closer());
4671 this._closers.delete(path);
4672}
4673
4674/**
4675 *
4676 * @param {Path} path
4677 * @param {Function} closer
4678 */
4679_addPathCloser(path, closer) {
4680 if (!closer) return;
4681 let list = this._closers.get(path);
4682 if (!list) {
4683 list = [];
4684 this._closers.set(path, list);
4685 }
4686 list.push(closer);
4687}
4688
4689_readdirp(root, opts) {
4690 if (this.closed) return;
4691 const options = {type: EV_ALL, alwaysStat: true, lstat: true, ...opts};
4692 let stream = readdirp(root, options);
4693 this._streams.add(stream);
4694 stream.once(STR_CLOSE, () => {
4695 stream = undefined;
4696 });
4697 stream.once(STR_END, () => {
4698 if (stream) {
4699 this._streams.delete(stream);
4700 stream = undefined;
4701 }
4702 });
4703 return stream;
4704}
4705
4706}
4707
4708// Export FSWatcher class
4709chokidar.FSWatcher = FSWatcher;
4710
4711/**
4712 * Instantiates watcher with paths to be tracked.
4713 * @param {String|Array<String>} paths file/directory paths and/or globs
4714 * @param {Object=} options chokidar opts
4715 * @returns an instance of FSWatcher for chaining.
4716 */
4717const watch = (paths, options) => {
4718 const watcher = new FSWatcher(options);
4719 watcher.add(paths);
4720 return watcher;
4721};
4722
4723chokidar.watch = watch;
4724
4725class FileWatcher {
4726 constructor(task, chokidarOptions) {
4727 this.transformWatchers = new Map();
4728 this.chokidarOptions = chokidarOptions;
4729 this.task = task;
4730 this.watcher = this.createWatcher(null);
4731 }
4732 close() {
4733 this.watcher.close();
4734 for (const watcher of this.transformWatchers.values()) {
4735 watcher.close();
4736 }
4737 }
4738 unwatch(id) {
4739 this.watcher.unwatch(id);
4740 const transformWatcher = this.transformWatchers.get(id);
4741 if (transformWatcher) {
4742 this.transformWatchers.delete(id);
4743 transformWatcher.close();
4744 }
4745 }
4746 watch(id, isTransformDependency) {
4747 var _a;
4748 if (isTransformDependency) {
4749 const watcher = (_a = this.transformWatchers.get(id)) !== null && _a !== void 0 ? _a : this.createWatcher(id);
4750 watcher.add(id);
4751 this.transformWatchers.set(id, watcher);
4752 }
4753 else {
4754 this.watcher.add(id);
4755 }
4756 }
4757 createWatcher(transformWatcherId) {
4758 const task = this.task;
4759 const isLinux = platform() === 'linux';
4760 const isTransformDependency = transformWatcherId !== null;
4761 const handleChange = (id, event) => {
4762 const changedId = transformWatcherId || id;
4763 if (isLinux) {
4764 // unwatching and watching fixes an issue with chokidar where on certain systems,
4765 // a file that was unlinked and immediately recreated would create a change event
4766 // but then no longer any further events
4767 watcher.unwatch(changedId);
4768 watcher.add(changedId);
4769 }
4770 task.invalidate(changedId, { event, isTransformDependency });
4771 };
4772 const watcher = chokidar
4773 .watch([], this.chokidarOptions)
4774 .on('add', id => handleChange(id, 'create'))
4775 .on('change', id => handleChange(id, 'update'))
4776 .on('unlink', id => handleChange(id, 'delete'));
4777 return watcher;
4778 }
4779}
4780
4781const eventsRewrites = {
4782 create: {
4783 create: 'buggy',
4784 delete: null,
4785 update: 'create'
4786 },
4787 delete: {
4788 create: 'update',
4789 delete: 'buggy',
4790 update: 'buggy'
4791 },
4792 update: {
4793 create: 'buggy',
4794 delete: 'delete',
4795 update: 'update'
4796 }
4797};
4798class Watcher {
4799 constructor(configs, emitter) {
4800 this.buildDelay = 0;
4801 this.buildTimeout = null;
4802 this.invalidatedIds = new Map();
4803 this.rerun = false;
4804 this.running = true;
4805 this.emitter = emitter;
4806 emitter.close = this.close.bind(this);
4807 this.tasks = configs.map(config => new Task(this, config));
4808 this.buildDelay = configs.reduce((buildDelay, { watch }) => watch && typeof watch.buildDelay === 'number'
4809 ? Math.max(buildDelay, watch.buildDelay)
4810 : buildDelay, this.buildDelay);
4811 process$1.nextTick(() => this.run());
4812 }
4813 async close() {
4814 if (this.buildTimeout)
4815 clearTimeout(this.buildTimeout);
4816 for (const task of this.tasks) {
4817 task.close();
4818 }
4819 await this.emitter.emitAndAwait('close');
4820 this.emitter.removeAllListeners();
4821 }
4822 invalidate(file) {
4823 if (file) {
4824 const prevEvent = this.invalidatedIds.get(file.id);
4825 const event = prevEvent ? eventsRewrites[prevEvent][file.event] : file.event;
4826 if (event === 'buggy') {
4827 //TODO: throws or warn? Currently just ignore, uses new event
4828 this.invalidatedIds.set(file.id, file.event);
4829 }
4830 else if (event === null) {
4831 this.invalidatedIds.delete(file.id);
4832 }
4833 else {
4834 this.invalidatedIds.set(file.id, event);
4835 }
4836 }
4837 if (this.running) {
4838 this.rerun = true;
4839 return;
4840 }
4841 if (this.buildTimeout)
4842 clearTimeout(this.buildTimeout);
4843 this.buildTimeout = setTimeout(async () => {
4844 this.buildTimeout = null;
4845 try {
4846 await Promise.all([...this.invalidatedIds].map(([id, event]) => this.emitter.emitAndAwait('change', id, { event })));
4847 this.invalidatedIds.clear();
4848 this.emitter.emit('restart');
4849 this.emitter.removeAwaited();
4850 this.run();
4851 }
4852 catch (error) {
4853 this.invalidatedIds.clear();
4854 this.emitter.emit('event', {
4855 code: 'ERROR',
4856 error,
4857 result: null
4858 });
4859 this.emitter.emit('event', {
4860 code: 'END'
4861 });
4862 }
4863 }, this.buildDelay);
4864 }
4865 async run() {
4866 this.running = true;
4867 this.emitter.emit('event', {
4868 code: 'START'
4869 });
4870 for (const task of this.tasks) {
4871 await task.run();
4872 }
4873 this.running = false;
4874 this.emitter.emit('event', {
4875 code: 'END'
4876 });
4877 if (this.rerun) {
4878 this.rerun = false;
4879 this.invalidate();
4880 }
4881 }
4882}
4883class Task {
4884 constructor(watcher, config) {
4885 this.cache = { modules: [] };
4886 this.watchFiles = [];
4887 this.closed = false;
4888 this.invalidated = true;
4889 this.watched = new Set();
4890 this.watcher = watcher;
4891 this.skipWrite = Boolean(config.watch && config.watch.skipWrite);
4892 this.options = mergeOptions(config);
4893 this.outputs = this.options.output;
4894 this.outputFiles = this.outputs.map(output => {
4895 if (output.file || output.dir)
4896 return resolve(output.file || output.dir);
4897 return undefined;
4898 });
4899 const watchOptions = this.options.watch || {};
4900 this.filter = createFilter(watchOptions.include, watchOptions.exclude);
4901 this.fileWatcher = new FileWatcher(this, {
4902 ...watchOptions.chokidar,
4903 disableGlobbing: true,
4904 ignoreInitial: true
4905 });
4906 }
4907 close() {
4908 this.closed = true;
4909 this.fileWatcher.close();
4910 }
4911 invalidate(id, details) {
4912 this.invalidated = true;
4913 if (details.isTransformDependency) {
4914 for (const module of this.cache.modules) {
4915 if (!module.transformDependencies.includes(id))
4916 continue;
4917 // effective invalidation
4918 module.originalCode = null;
4919 }
4920 }
4921 this.watcher.invalidate({ event: details.event, id });
4922 }
4923 async run() {
4924 if (!this.invalidated)
4925 return;
4926 this.invalidated = false;
4927 const options = {
4928 ...this.options,
4929 cache: this.cache
4930 };
4931 const start = Date.now();
4932 this.watcher.emitter.emit('event', {
4933 code: 'BUNDLE_START',
4934 input: this.options.input,
4935 output: this.outputFiles
4936 });
4937 let result = null;
4938 try {
4939 result = await rollupInternal(options, this.watcher.emitter);
4940 if (this.closed) {
4941 return;
4942 }
4943 this.updateWatchedFiles(result);
4944 this.skipWrite || (await Promise.all(this.outputs.map(output => result.write(output))));
4945 this.watcher.emitter.emit('event', {
4946 code: 'BUNDLE_END',
4947 duration: Date.now() - start,
4948 input: this.options.input,
4949 output: this.outputFiles,
4950 result
4951 });
4952 }
4953 catch (error) {
4954 if (!this.closed) {
4955 if (Array.isArray(error.watchFiles)) {
4956 for (const id of error.watchFiles) {
4957 this.watchFile(id);
4958 }
4959 }
4960 if (error.id) {
4961 this.cache.modules = this.cache.modules.filter(module => module.id !== error.id);
4962 }
4963 }
4964 this.watcher.emitter.emit('event', {
4965 code: 'ERROR',
4966 error,
4967 result
4968 });
4969 }
4970 }
4971 updateWatchedFiles(result) {
4972 const previouslyWatched = this.watched;
4973 this.watched = new Set();
4974 this.watchFiles = result.watchFiles;
4975 this.cache = result.cache;
4976 for (const id of this.watchFiles) {
4977 this.watchFile(id);
4978 }
4979 for (const module of this.cache.modules) {
4980 for (const depId of module.transformDependencies) {
4981 this.watchFile(depId, true);
4982 }
4983 }
4984 for (const id of previouslyWatched) {
4985 if (!this.watched.has(id)) {
4986 this.fileWatcher.unwatch(id);
4987 }
4988 }
4989 }
4990 watchFile(id, isTransformDependency = false) {
4991 if (!this.filter(id))
4992 return;
4993 this.watched.add(id);
4994 if (this.outputFiles.some(file => file === id)) {
4995 throw new Error('Cannot import the generated bundle');
4996 }
4997 // this is necessary to ensure that any 'renamed' files
4998 // continue to be watched following an error
4999 this.fileWatcher.watch(id, isTransformDependency);
5000 }
5001}
5002
5003export { Task, Watcher };
Note: See TracBrowser for help on using the repository browser.