feat: Add presence heartbeat for Matrix online status
- matrix-gateway: POST /internal/matrix/presence/online endpoint - usePresenceHeartbeat hook with activity tracking - Auto away after 5 min inactivity - Offline on page close/visibility change - Integrated in MatrixChatRoom component
This commit is contained in:
21
node_modules/chokidar/LICENSE
generated
vendored
Normal file
21
node_modules/chokidar/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2019 Paul Miller (https://paulmillr.com), Elan Shanker
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the “Software”), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
308
node_modules/chokidar/README.md
generated
vendored
Normal file
308
node_modules/chokidar/README.md
generated
vendored
Normal file
@@ -0,0 +1,308 @@
|
||||
# Chokidar [](https://github.com/paulmillr/chokidar) [](https://github.com/paulmillr/chokidar)
|
||||
|
||||
> Minimal and efficient cross-platform file watching library
|
||||
|
||||
[](https://www.npmjs.com/package/chokidar)
|
||||
|
||||
## Why?
|
||||
|
||||
Node.js `fs.watch`:
|
||||
|
||||
* Doesn't report filenames on MacOS.
|
||||
* Doesn't report events at all when using editors like Sublime on MacOS.
|
||||
* Often reports events twice.
|
||||
* Emits most changes as `rename`.
|
||||
* Does not provide an easy way to recursively watch file trees.
|
||||
* Does not support recursive watching on Linux.
|
||||
|
||||
Node.js `fs.watchFile`:
|
||||
|
||||
* Almost as bad at event handling.
|
||||
* Also does not provide any recursive watching.
|
||||
* Results in high CPU utilization.
|
||||
|
||||
Chokidar resolves these problems.
|
||||
|
||||
Initially made for **[Brunch](https://brunch.io/)** (an ultra-swift web app build tool), it is now used in
|
||||
[Microsoft's Visual Studio Code](https://github.com/microsoft/vscode),
|
||||
[gulp](https://github.com/gulpjs/gulp/),
|
||||
[karma](https://karma-runner.github.io/),
|
||||
[PM2](https://github.com/Unitech/PM2),
|
||||
[browserify](http://browserify.org/),
|
||||
[webpack](https://webpack.github.io/),
|
||||
[BrowserSync](https://www.browsersync.io/),
|
||||
and [many others](https://www.npmjs.com/browse/depended/chokidar).
|
||||
It has proven itself in production environments.
|
||||
|
||||
Version 3 is out! Check out our blog post about it: [Chokidar 3: How to save 32TB of traffic every week](https://paulmillr.com/posts/chokidar-3-save-32tb-of-traffic/)
|
||||
|
||||
## How?
|
||||
|
||||
Chokidar does still rely on the Node.js core `fs` module, but when using
|
||||
`fs.watch` and `fs.watchFile` for watching, it normalizes the events it
|
||||
receives, often checking for truth by getting file stats and/or dir contents.
|
||||
|
||||
On MacOS, chokidar by default uses a native extension exposing the Darwin
|
||||
`FSEvents` API. This provides very efficient recursive watching compared with
|
||||
implementations like `kqueue` available on most \*nix platforms. Chokidar still
|
||||
does have to do some work to normalize the events received that way as well.
|
||||
|
||||
On most other platforms, the `fs.watch`-based implementation is the default, which
|
||||
avoids polling and keeps CPU usage down. Be advised that chokidar will initiate
|
||||
watchers recursively for everything within scope of the paths that have been
|
||||
specified, so be judicious about not wasting system resources by watching much
|
||||
more than needed.
|
||||
|
||||
## Getting started
|
||||
|
||||
Install with npm:
|
||||
|
||||
```sh
|
||||
npm install chokidar
|
||||
```
|
||||
|
||||
Then `require` and use it in your code:
|
||||
|
||||
```javascript
|
||||
const chokidar = require('chokidar');
|
||||
|
||||
// One-liner for current directory
|
||||
chokidar.watch('.').on('all', (event, path) => {
|
||||
console.log(event, path);
|
||||
});
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```javascript
|
||||
// Example of a more typical implementation structure
|
||||
|
||||
// Initialize watcher.
|
||||
const watcher = chokidar.watch('file, dir, glob, or array', {
|
||||
ignored: /(^|[\/\\])\../, // ignore dotfiles
|
||||
persistent: true
|
||||
});
|
||||
|
||||
// Something to use when events are received.
|
||||
const log = console.log.bind(console);
|
||||
// Add event listeners.
|
||||
watcher
|
||||
.on('add', path => log(`File ${path} has been added`))
|
||||
.on('change', path => log(`File ${path} has been changed`))
|
||||
.on('unlink', path => log(`File ${path} has been removed`));
|
||||
|
||||
// More possible events.
|
||||
watcher
|
||||
.on('addDir', path => log(`Directory ${path} has been added`))
|
||||
.on('unlinkDir', path => log(`Directory ${path} has been removed`))
|
||||
.on('error', error => log(`Watcher error: ${error}`))
|
||||
.on('ready', () => log('Initial scan complete. Ready for changes'))
|
||||
.on('raw', (event, path, details) => { // internal
|
||||
log('Raw event info:', event, path, details);
|
||||
});
|
||||
|
||||
// 'add', 'addDir' and 'change' events also receive stat() results as second
|
||||
// argument when available: https://nodejs.org/api/fs.html#fs_class_fs_stats
|
||||
watcher.on('change', (path, stats) => {
|
||||
if (stats) console.log(`File ${path} changed size to ${stats.size}`);
|
||||
});
|
||||
|
||||
// Watch new files.
|
||||
watcher.add('new-file');
|
||||
watcher.add(['new-file-2', 'new-file-3', '**/other-file*']);
|
||||
|
||||
// Get list of actual paths being watched on the filesystem
|
||||
var watchedPaths = watcher.getWatched();
|
||||
|
||||
// Un-watch some files.
|
||||
await watcher.unwatch('new-file*');
|
||||
|
||||
// Stop watching.
|
||||
// The method is async!
|
||||
watcher.close().then(() => console.log('closed'));
|
||||
|
||||
// Full list of options. See below for descriptions.
|
||||
// Do not use this example!
|
||||
chokidar.watch('file', {
|
||||
persistent: true,
|
||||
|
||||
ignored: '*.txt',
|
||||
ignoreInitial: false,
|
||||
followSymlinks: true,
|
||||
cwd: '.',
|
||||
disableGlobbing: false,
|
||||
|
||||
usePolling: false,
|
||||
interval: 100,
|
||||
binaryInterval: 300,
|
||||
alwaysStat: false,
|
||||
depth: 99,
|
||||
awaitWriteFinish: {
|
||||
stabilityThreshold: 2000,
|
||||
pollInterval: 100
|
||||
},
|
||||
|
||||
ignorePermissionErrors: false,
|
||||
atomic: true // or a custom 'atomicity delay', in milliseconds (default 100)
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
`chokidar.watch(paths, [options])`
|
||||
|
||||
* `paths` (string or array of strings). Paths to files, dirs to be watched
|
||||
recursively, or glob patterns.
|
||||
- Note: globs must not contain windows separators (`\`),
|
||||
because that's how they work by the standard —
|
||||
you'll need to replace them with forward slashes (`/`).
|
||||
- Note 2: for additional glob documentation, check out low-level
|
||||
library: [picomatch](https://github.com/micromatch/picomatch).
|
||||
* `options` (object) Options object as defined below:
|
||||
|
||||
#### Persistence
|
||||
|
||||
* `persistent` (default: `true`). Indicates whether the process
|
||||
should continue to run as long as files are being watched. If set to
|
||||
`false` when using `fsevents` to watch, no more events will be emitted
|
||||
after `ready`, even if the process continues to run.
|
||||
|
||||
#### Path filtering
|
||||
|
||||
* `ignored` ([anymatch](https://github.com/es128/anymatch)-compatible definition)
|
||||
Defines files/paths to be ignored. The whole relative or absolute path is
|
||||
tested, not just filename. If a function with two arguments is provided, it
|
||||
gets called twice per path - once with a single argument (the path), second
|
||||
time with two arguments (the path and the
|
||||
[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)
|
||||
object of that path).
|
||||
* `ignoreInitial` (default: `false`). If set to `false` then `add`/`addDir` events are also emitted for matching paths while
|
||||
instantiating the watching as chokidar discovers these file paths (before the `ready` event).
|
||||
* `followSymlinks` (default: `true`). When `false`, only the
|
||||
symlinks themselves will be watched for changes instead of following
|
||||
the link references and bubbling events through the link's path.
|
||||
* `cwd` (no default). The base directory from which watch `paths` are to be
|
||||
derived. Paths emitted with events will be relative to this.
|
||||
* `disableGlobbing` (default: `false`). If set to `true` then the strings passed to `.watch()` and `.add()` are treated as
|
||||
literal path names, even if they look like globs.
|
||||
|
||||
#### Performance
|
||||
|
||||
* `usePolling` (default: `false`).
|
||||
Whether to use fs.watchFile (backed by polling), or fs.watch. If polling
|
||||
leads to high CPU utilization, consider setting this to `false`. It is
|
||||
typically necessary to **set this to `true` to successfully watch files over
|
||||
a network**, and it may be necessary to successfully watch files in other
|
||||
non-standard situations. Setting to `true` explicitly on MacOS overrides the
|
||||
`useFsEvents` default. You may also set the CHOKIDAR_USEPOLLING env variable
|
||||
to true (1) or false (0) in order to override this option.
|
||||
* _Polling-specific settings_ (effective when `usePolling: true`)
|
||||
* `interval` (default: `100`). Interval of file system polling, in milliseconds. You may also
|
||||
set the CHOKIDAR_INTERVAL env variable to override this option.
|
||||
* `binaryInterval` (default: `300`). Interval of file system
|
||||
polling for binary files.
|
||||
([see list of binary extensions](https://github.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json))
|
||||
* `useFsEvents` (default: `true` on MacOS). Whether to use the
|
||||
`fsevents` watching interface if available. When set to `true` explicitly
|
||||
and `fsevents` is available this supercedes the `usePolling` setting. When
|
||||
set to `false` on MacOS, `usePolling: true` becomes the default.
|
||||
* `alwaysStat` (default: `false`). If relying upon the
|
||||
[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)
|
||||
object that may get passed with `add`, `addDir`, and `change` events, set
|
||||
this to `true` to ensure it is provided even in cases where it wasn't
|
||||
already available from the underlying watch events.
|
||||
* `depth` (default: `undefined`). If set, limits how many levels of
|
||||
subdirectories will be traversed.
|
||||
* `awaitWriteFinish` (default: `false`).
|
||||
By default, the `add` event will fire when a file first appears on disk, before
|
||||
the entire file has been written. Furthermore, in some cases some `change`
|
||||
events will be emitted while the file is being written. In some cases,
|
||||
especially when watching for large files there will be a need to wait for the
|
||||
write operation to finish before responding to a file creation or modification.
|
||||
Setting `awaitWriteFinish` to `true` (or a truthy value) will poll file size,
|
||||
holding its `add` and `change` events until the size does not change for a
|
||||
configurable amount of time. The appropriate duration setting is heavily
|
||||
dependent on the OS and hardware. For accurate detection this parameter should
|
||||
be relatively high, making file watching much less responsive.
|
||||
Use with caution.
|
||||
* *`options.awaitWriteFinish` can be set to an object in order to adjust
|
||||
timing params:*
|
||||
* `awaitWriteFinish.stabilityThreshold` (default: 2000). Amount of time in
|
||||
milliseconds for a file size to remain constant before emitting its event.
|
||||
* `awaitWriteFinish.pollInterval` (default: 100). File size polling interval, in milliseconds.
|
||||
|
||||
#### Errors
|
||||
|
||||
* `ignorePermissionErrors` (default: `false`). Indicates whether to watch files
|
||||
that don't have read permissions if possible. If watching fails due to `EPERM`
|
||||
or `EACCES` with this set to `true`, the errors will be suppressed silently.
|
||||
* `atomic` (default: `true` if `useFsEvents` and `usePolling` are `false`).
|
||||
Automatically filters out artifacts that occur when using editors that use
|
||||
"atomic writes" instead of writing directly to the source file. If a file is
|
||||
re-added within 100 ms of being deleted, Chokidar emits a `change` event
|
||||
rather than `unlink` then `add`. If the default of 100 ms does not work well
|
||||
for you, you can override it by setting `atomic` to a custom value, in
|
||||
milliseconds.
|
||||
|
||||
### Methods & Events
|
||||
|
||||
`chokidar.watch()` produces an instance of `FSWatcher`. Methods of `FSWatcher`:
|
||||
|
||||
* `.add(path / paths)`: Add files, directories, or glob patterns for tracking.
|
||||
Takes an array of strings or just one string.
|
||||
* `.on(event, callback)`: Listen for an FS event.
|
||||
Available events: `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `ready`,
|
||||
`raw`, `error`.
|
||||
Additionally `all` is available which gets emitted with the underlying event
|
||||
name and path for every event other than `ready`, `raw`, and `error`. `raw` is internal, use it carefully.
|
||||
* `.unwatch(path / paths)`: Stop watching files, directories, or glob patterns.
|
||||
Takes an array of strings or just one string.
|
||||
* `.close()`: **async** Removes all listeners from watched files. Asynchronous, returns Promise. Use with `await` to ensure bugs don't happen.
|
||||
* `.getWatched()`: Returns an object representing all the paths on the file
|
||||
system being watched by this `FSWatcher` instance. The object's keys are all the
|
||||
directories (using absolute paths unless the `cwd` option was used), and the
|
||||
values are arrays of the names of the items contained in each directory.
|
||||
|
||||
## CLI
|
||||
|
||||
If you need a CLI interface for your file watching, check out
|
||||
[chokidar-cli](https://github.com/open-cli-tools/chokidar-cli), allowing you to
|
||||
execute a command on each change, or get a stdio stream of change events.
|
||||
|
||||
## Install Troubleshooting
|
||||
|
||||
* `npm WARN optional dep failed, continuing fsevents@n.n.n`
|
||||
* This message is normal part of how `npm` handles optional dependencies and is
|
||||
not indicative of a problem. Even if accompanied by other related error messages,
|
||||
Chokidar should function properly.
|
||||
|
||||
* `TypeError: fsevents is not a constructor`
|
||||
* Update chokidar by doing `rm -rf node_modules package-lock.json yarn.lock && npm install`, or update your dependency that uses chokidar.
|
||||
|
||||
* Chokidar is producing `ENOSP` error on Linux, like this:
|
||||
* `bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell`
|
||||
`Error: watch /home/ ENOSPC`
|
||||
* This means Chokidar ran out of file handles and you'll need to increase their count by executing the following command in Terminal:
|
||||
`echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`
|
||||
|
||||
## Changelog
|
||||
|
||||
For more detailed changelog, see [`full_changelog.md`](.github/full_changelog.md).
|
||||
- **v3.5 (Jan 6, 2021):** Support for ARM Macs with Apple Silicon. Fixes for deleted symlinks.
|
||||
- **v3.4 (Apr 26, 2020):** Support for directory-based symlinks. Fixes for macos file replacement.
|
||||
- **v3.3 (Nov 2, 2019):** `FSWatcher#close()` method became async. That fixes IO race conditions related to close method.
|
||||
- **v3.2 (Oct 1, 2019):** Improve Linux RAM usage by 50%. Race condition fixes. Windows glob fixes. Improve stability by using tight range of dependency versions.
|
||||
- **v3.1 (Sep 16, 2019):** dotfiles are no longer filtered out by default. Use `ignored` option if needed. Improve initial Linux scan time by 50%.
|
||||
- **v3 (Apr 30, 2019):** massive CPU & RAM consumption improvements; reduces deps / package size by a factor of 17x and bumps Node.js requirement to v8.16 and higher.
|
||||
- **v2 (Dec 29, 2017):** Globs are now posix-style-only; without windows support. Tons of bugfixes.
|
||||
- **v1 (Apr 7, 2015):** Glob support, symlink support, tons of bugfixes. Node 0.8+ is supported
|
||||
- **v0.1 (Apr 20, 2012):** Initial release, extracted from [Brunch](https://github.com/brunch/brunch/blob/9847a065aea300da99bd0753f90354cde9de1261/src/helpers.coffee#L66)
|
||||
|
||||
## Also
|
||||
|
||||
Why was chokidar named this way? What's the meaning behind it?
|
||||
|
||||
>Chowkidar is a transliteration of a Hindi word meaning 'watchman, gatekeeper', चौकीदार. This ultimately comes from Sanskrit _ चतुष्क_ (crossway, quadrangle, consisting-of-four). This word is also used in other languages like Urdu as (چوکیدار) which is widely used in Pakistan and India.
|
||||
|
||||
## License
|
||||
|
||||
MIT (c) Paul Miller (<https://paulmillr.com>), see [LICENSE](LICENSE) file.
|
||||
973
node_modules/chokidar/index.js
generated
vendored
Normal file
973
node_modules/chokidar/index.js
generated
vendored
Normal file
@@ -0,0 +1,973 @@
|
||||
'use strict';
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const fs = require('fs');
|
||||
const sysPath = require('path');
|
||||
const { promisify } = require('util');
|
||||
const readdirp = require('readdirp');
|
||||
const anymatch = require('anymatch').default;
|
||||
const globParent = require('glob-parent');
|
||||
const isGlob = require('is-glob');
|
||||
const braces = require('braces');
|
||||
const normalizePath = require('normalize-path');
|
||||
|
||||
const NodeFsHandler = require('./lib/nodefs-handler');
|
||||
const FsEventsHandler = require('./lib/fsevents-handler');
|
||||
const {
|
||||
EV_ALL,
|
||||
EV_READY,
|
||||
EV_ADD,
|
||||
EV_CHANGE,
|
||||
EV_UNLINK,
|
||||
EV_ADD_DIR,
|
||||
EV_UNLINK_DIR,
|
||||
EV_RAW,
|
||||
EV_ERROR,
|
||||
|
||||
STR_CLOSE,
|
||||
STR_END,
|
||||
|
||||
BACK_SLASH_RE,
|
||||
DOUBLE_SLASH_RE,
|
||||
SLASH_OR_BACK_SLASH_RE,
|
||||
DOT_RE,
|
||||
REPLACER_RE,
|
||||
|
||||
SLASH,
|
||||
SLASH_SLASH,
|
||||
BRACE_START,
|
||||
BANG,
|
||||
ONE_DOT,
|
||||
TWO_DOTS,
|
||||
GLOBSTAR,
|
||||
SLASH_GLOBSTAR,
|
||||
ANYMATCH_OPTS,
|
||||
STRING_TYPE,
|
||||
FUNCTION_TYPE,
|
||||
EMPTY_STR,
|
||||
EMPTY_FN,
|
||||
|
||||
isWindows,
|
||||
isMacos,
|
||||
isIBMi
|
||||
} = require('./lib/constants');
|
||||
|
||||
const stat = promisify(fs.stat);
|
||||
const readdir = promisify(fs.readdir);
|
||||
|
||||
/**
|
||||
* @typedef {String} Path
|
||||
* @typedef {'all'|'add'|'addDir'|'change'|'unlink'|'unlinkDir'|'raw'|'error'|'ready'} EventName
|
||||
* @typedef {'readdir'|'watch'|'add'|'remove'|'change'} ThrottleType
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @typedef {Object} WatchHelpers
|
||||
* @property {Boolean} followSymlinks
|
||||
* @property {'stat'|'lstat'} statMethod
|
||||
* @property {Path} path
|
||||
* @property {Path} watchPath
|
||||
* @property {Function} entryPath
|
||||
* @property {Boolean} hasGlob
|
||||
* @property {Object} globFilter
|
||||
* @property {Function} filterPath
|
||||
* @property {Function} filterDir
|
||||
*/
|
||||
|
||||
const arrify = (value = []) => Array.isArray(value) ? value : [value];
|
||||
const flatten = (list, result = []) => {
|
||||
list.forEach(item => {
|
||||
if (Array.isArray(item)) {
|
||||
flatten(item, result);
|
||||
} else {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const unifyPaths = (paths_) => {
|
||||
/**
|
||||
* @type {Array<String>}
|
||||
*/
|
||||
const paths = flatten(arrify(paths_));
|
||||
if (!paths.every(p => typeof p === STRING_TYPE)) {
|
||||
throw new TypeError(`Non-string provided as watch path: ${paths}`);
|
||||
}
|
||||
return paths.map(normalizePathToUnix);
|
||||
};
|
||||
|
||||
// If SLASH_SLASH occurs at the beginning of path, it is not replaced
|
||||
// because "//StoragePC/DrivePool/Movies" is a valid network path
|
||||
const toUnix = (string) => {
|
||||
let str = string.replace(BACK_SLASH_RE, SLASH);
|
||||
let prepend = false;
|
||||
if (str.startsWith(SLASH_SLASH)) {
|
||||
prepend = true;
|
||||
}
|
||||
while (str.match(DOUBLE_SLASH_RE)) {
|
||||
str = str.replace(DOUBLE_SLASH_RE, SLASH);
|
||||
}
|
||||
if (prepend) {
|
||||
str = SLASH + str;
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
// Our version of upath.normalize
|
||||
// TODO: this is not equal to path-normalize module - investigate why
|
||||
const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));
|
||||
|
||||
const normalizeIgnored = (cwd = EMPTY_STR) => (path) => {
|
||||
if (typeof path !== STRING_TYPE) return path;
|
||||
return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));
|
||||
};
|
||||
|
||||
const getAbsolutePath = (path, cwd) => {
|
||||
if (sysPath.isAbsolute(path)) {
|
||||
return path;
|
||||
}
|
||||
if (path.startsWith(BANG)) {
|
||||
return BANG + sysPath.join(cwd, path.slice(1));
|
||||
}
|
||||
return sysPath.join(cwd, path);
|
||||
};
|
||||
|
||||
const undef = (opts, key) => opts[key] === undefined;
|
||||
|
||||
/**
|
||||
* Directory entry.
|
||||
* @property {Path} path
|
||||
* @property {Set<Path>} items
|
||||
*/
|
||||
class DirEntry {
|
||||
/**
|
||||
* @param {Path} dir
|
||||
* @param {Function} removeWatcher
|
||||
*/
|
||||
constructor(dir, removeWatcher) {
|
||||
this.path = dir;
|
||||
this._removeWatcher = removeWatcher;
|
||||
/** @type {Set<Path>} */
|
||||
this.items = new Set();
|
||||
}
|
||||
|
||||
add(item) {
|
||||
const {items} = this;
|
||||
if (!items) return;
|
||||
if (item !== ONE_DOT && item !== TWO_DOTS) items.add(item);
|
||||
}
|
||||
|
||||
async remove(item) {
|
||||
const {items} = this;
|
||||
if (!items) return;
|
||||
items.delete(item);
|
||||
if (items.size > 0) return;
|
||||
|
||||
const dir = this.path;
|
||||
try {
|
||||
await readdir(dir);
|
||||
} catch (err) {
|
||||
if (this._removeWatcher) {
|
||||
this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
has(item) {
|
||||
const {items} = this;
|
||||
if (!items) return;
|
||||
return items.has(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Array<String>}
|
||||
*/
|
||||
getChildren() {
|
||||
const {items} = this;
|
||||
if (!items) return;
|
||||
return [...items.values()];
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.items.clear();
|
||||
delete this.path;
|
||||
delete this._removeWatcher;
|
||||
delete this.items;
|
||||
Object.freeze(this);
|
||||
}
|
||||
}
|
||||
|
||||
const STAT_METHOD_F = 'stat';
|
||||
const STAT_METHOD_L = 'lstat';
|
||||
class WatchHelper {
|
||||
constructor(path, watchPath, follow, fsw) {
|
||||
this.fsw = fsw;
|
||||
this.path = path = path.replace(REPLACER_RE, EMPTY_STR);
|
||||
this.watchPath = watchPath;
|
||||
this.fullWatchPath = sysPath.resolve(watchPath);
|
||||
this.hasGlob = watchPath !== path;
|
||||
/** @type {object|boolean} */
|
||||
if (path === EMPTY_STR) this.hasGlob = false;
|
||||
this.globSymlink = this.hasGlob && follow ? undefined : false;
|
||||
this.globFilter = this.hasGlob ? anymatch(path, undefined, ANYMATCH_OPTS) : false;
|
||||
this.dirParts = this.getDirParts(path);
|
||||
this.dirParts.forEach((parts) => {
|
||||
if (parts.length > 1) parts.pop();
|
||||
});
|
||||
this.followSymlinks = follow;
|
||||
this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
|
||||
}
|
||||
|
||||
checkGlobSymlink(entry) {
|
||||
// only need to resolve once
|
||||
// first entry should always have entry.parentDir === EMPTY_STR
|
||||
if (this.globSymlink === undefined) {
|
||||
this.globSymlink = entry.fullParentDir === this.fullWatchPath ?
|
||||
false : {realPath: entry.fullParentDir, linkPath: this.fullWatchPath};
|
||||
}
|
||||
|
||||
if (this.globSymlink) {
|
||||
return entry.fullPath.replace(this.globSymlink.realPath, this.globSymlink.linkPath);
|
||||
}
|
||||
|
||||
return entry.fullPath;
|
||||
}
|
||||
|
||||
entryPath(entry) {
|
||||
return sysPath.join(this.watchPath,
|
||||
sysPath.relative(this.watchPath, this.checkGlobSymlink(entry))
|
||||
);
|
||||
}
|
||||
|
||||
filterPath(entry) {
|
||||
const {stats} = entry;
|
||||
if (stats && stats.isSymbolicLink()) return this.filterDir(entry);
|
||||
const resolvedPath = this.entryPath(entry);
|
||||
const matchesGlob = this.hasGlob && typeof this.globFilter === FUNCTION_TYPE ?
|
||||
this.globFilter(resolvedPath) : true;
|
||||
return matchesGlob &&
|
||||
this.fsw._isntIgnored(resolvedPath, stats) &&
|
||||
this.fsw._hasReadPermissions(stats);
|
||||
}
|
||||
|
||||
getDirParts(path) {
|
||||
if (!this.hasGlob) return [];
|
||||
const parts = [];
|
||||
const expandedPath = path.includes(BRACE_START) ? braces.expand(path) : [path];
|
||||
expandedPath.forEach((path) => {
|
||||
parts.push(sysPath.relative(this.watchPath, path).split(SLASH_OR_BACK_SLASH_RE));
|
||||
});
|
||||
return parts;
|
||||
}
|
||||
|
||||
filterDir(entry) {
|
||||
if (this.hasGlob) {
|
||||
const entryParts = this.getDirParts(this.checkGlobSymlink(entry));
|
||||
let globstar = false;
|
||||
this.unmatchedGlob = !this.dirParts.some((parts) => {
|
||||
return parts.every((part, i) => {
|
||||
if (part === GLOBSTAR) globstar = true;
|
||||
return globstar || !entryParts[0][i] || anymatch(part, entryParts[0][i], ANYMATCH_OPTS);
|
||||
});
|
||||
});
|
||||
}
|
||||
return !this.unmatchedGlob && this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches files & directories for changes. Emitted events:
|
||||
* `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
|
||||
*
|
||||
* new FSWatcher()
|
||||
* .add(directories)
|
||||
* .on('add', path => log('File', path, 'was added'))
|
||||
*/
|
||||
class FSWatcher extends EventEmitter {
|
||||
// Not indenting methods for history sake; for now.
|
||||
constructor(_opts) {
|
||||
super();
|
||||
|
||||
const opts = {};
|
||||
if (_opts) Object.assign(opts, _opts); // for frozen objects
|
||||
|
||||
/** @type {Map<String, DirEntry>} */
|
||||
this._watched = new Map();
|
||||
/** @type {Map<String, Array>} */
|
||||
this._closers = new Map();
|
||||
/** @type {Set<String>} */
|
||||
this._ignoredPaths = new Set();
|
||||
|
||||
/** @type {Map<ThrottleType, Map>} */
|
||||
this._throttled = new Map();
|
||||
|
||||
/** @type {Map<Path, String|Boolean>} */
|
||||
this._symlinkPaths = new Map();
|
||||
|
||||
this._streams = new Set();
|
||||
this.closed = false;
|
||||
|
||||
// Set up default options.
|
||||
if (undef(opts, 'persistent')) opts.persistent = true;
|
||||
if (undef(opts, 'ignoreInitial')) opts.ignoreInitial = false;
|
||||
if (undef(opts, 'ignorePermissionErrors')) opts.ignorePermissionErrors = false;
|
||||
if (undef(opts, 'interval')) opts.interval = 100;
|
||||
if (undef(opts, 'binaryInterval')) opts.binaryInterval = 300;
|
||||
if (undef(opts, 'disableGlobbing')) opts.disableGlobbing = false;
|
||||
opts.enableBinaryInterval = opts.binaryInterval !== opts.interval;
|
||||
|
||||
// Enable fsevents on OS X when polling isn't explicitly enabled.
|
||||
if (undef(opts, 'useFsEvents')) opts.useFsEvents = !opts.usePolling;
|
||||
|
||||
// If we can't use fsevents, ensure the options reflect it's disabled.
|
||||
const canUseFsEvents = FsEventsHandler.canUse();
|
||||
if (!canUseFsEvents) opts.useFsEvents = false;
|
||||
|
||||
// Use polling on Mac if not using fsevents.
|
||||
// Other platforms use non-polling fs_watch.
|
||||
if (undef(opts, 'usePolling') && !opts.useFsEvents) {
|
||||
opts.usePolling = isMacos;
|
||||
}
|
||||
|
||||
// Always default to polling on IBM i because fs.watch() is not available on IBM i.
|
||||
if(isIBMi) {
|
||||
opts.usePolling = true;
|
||||
}
|
||||
|
||||
// Global override (useful for end-developers that need to force polling for all
|
||||
// instances of chokidar, regardless of usage/dependency depth)
|
||||
const envPoll = process.env.CHOKIDAR_USEPOLLING;
|
||||
if (envPoll !== undefined) {
|
||||
const envLower = envPoll.toLowerCase();
|
||||
|
||||
if (envLower === 'false' || envLower === '0') {
|
||||
opts.usePolling = false;
|
||||
} else if (envLower === 'true' || envLower === '1') {
|
||||
opts.usePolling = true;
|
||||
} else {
|
||||
opts.usePolling = !!envLower;
|
||||
}
|
||||
}
|
||||
const envInterval = process.env.CHOKIDAR_INTERVAL;
|
||||
if (envInterval) {
|
||||
opts.interval = Number.parseInt(envInterval, 10);
|
||||
}
|
||||
|
||||
// Editor atomic write normalization enabled by default with fs.watch
|
||||
if (undef(opts, 'atomic')) opts.atomic = !opts.usePolling && !opts.useFsEvents;
|
||||
if (opts.atomic) this._pendingUnlinks = new Map();
|
||||
|
||||
if (undef(opts, 'followSymlinks')) opts.followSymlinks = true;
|
||||
|
||||
if (undef(opts, 'awaitWriteFinish')) opts.awaitWriteFinish = false;
|
||||
if (opts.awaitWriteFinish === true) opts.awaitWriteFinish = {};
|
||||
const awf = opts.awaitWriteFinish;
|
||||
if (awf) {
|
||||
if (!awf.stabilityThreshold) awf.stabilityThreshold = 2000;
|
||||
if (!awf.pollInterval) awf.pollInterval = 100;
|
||||
this._pendingWrites = new Map();
|
||||
}
|
||||
if (opts.ignored) opts.ignored = arrify(opts.ignored);
|
||||
|
||||
let readyCalls = 0;
|
||||
this._emitReady = () => {
|
||||
readyCalls++;
|
||||
if (readyCalls >= this._readyCount) {
|
||||
this._emitReady = EMPTY_FN;
|
||||
this._readyEmitted = true;
|
||||
// use process.nextTick to allow time for listener to be bound
|
||||
process.nextTick(() => this.emit(EV_READY));
|
||||
}
|
||||
};
|
||||
this._emitRaw = (...args) => this.emit(EV_RAW, ...args);
|
||||
this._readyEmitted = false;
|
||||
this.options = opts;
|
||||
|
||||
// Initialize with proper watcher.
|
||||
if (opts.useFsEvents) {
|
||||
this._fsEventsHandler = new FsEventsHandler(this);
|
||||
} else {
|
||||
this._nodeFsHandler = new NodeFsHandler(this);
|
||||
}
|
||||
|
||||
// You’re frozen when your heart’s not open.
|
||||
Object.freeze(opts);
|
||||
}
|
||||
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* Adds paths to be watched on an existing FSWatcher instance
|
||||
* @param {Path|Array<Path>} paths_
|
||||
* @param {String=} _origAdd private; for handling non-existent paths to be watched
|
||||
* @param {Boolean=} _internal private; indicates a non-user add
|
||||
* @returns {FSWatcher} for chaining
|
||||
*/
|
||||
add(paths_, _origAdd, _internal) {
|
||||
const {cwd, disableGlobbing} = this.options;
|
||||
this.closed = false;
|
||||
let paths = unifyPaths(paths_);
|
||||
if (cwd) {
|
||||
paths = paths.map((path) => {
|
||||
const absPath = getAbsolutePath(path, cwd);
|
||||
|
||||
// Check `path` instead of `absPath` because the cwd portion can't be a glob
|
||||
if (disableGlobbing || !isGlob(path)) {
|
||||
return absPath;
|
||||
}
|
||||
return normalizePath(absPath);
|
||||
});
|
||||
}
|
||||
|
||||
// set aside negated glob strings
|
||||
paths = paths.filter((path) => {
|
||||
if (path.startsWith(BANG)) {
|
||||
this._ignoredPaths.add(path.slice(1));
|
||||
return false;
|
||||
}
|
||||
|
||||
// if a path is being added that was previously ignored, stop ignoring it
|
||||
this._ignoredPaths.delete(path);
|
||||
this._ignoredPaths.delete(path + SLASH_GLOBSTAR);
|
||||
|
||||
// reset the cached userIgnored anymatch fn
|
||||
// to make ignoredPaths changes effective
|
||||
this._userIgnored = undefined;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (this.options.useFsEvents && this._fsEventsHandler) {
|
||||
if (!this._readyCount) this._readyCount = paths.length;
|
||||
if (this.options.persistent) this._readyCount += paths.length;
|
||||
paths.forEach((path) => this._fsEventsHandler._addToFsEvents(path));
|
||||
} else {
|
||||
if (!this._readyCount) this._readyCount = 0;
|
||||
this._readyCount += paths.length;
|
||||
Promise.all(
|
||||
paths.map(async path => {
|
||||
const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, 0, 0, _origAdd);
|
||||
if (res) this._emitReady();
|
||||
return res;
|
||||
})
|
||||
).then(results => {
|
||||
if (this.closed) return;
|
||||
results.filter(item => item).forEach(item => {
|
||||
this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close watchers or start ignoring events from specified paths.
|
||||
* @param {Path|Array<Path>} paths_ - string or array of strings, file/directory paths and/or globs
|
||||
* @returns {FSWatcher} for chaining
|
||||
*/
|
||||
unwatch(paths_) {
|
||||
if (this.closed) return this;
|
||||
const paths = unifyPaths(paths_);
|
||||
const {cwd} = this.options;
|
||||
|
||||
paths.forEach((path) => {
|
||||
// convert to absolute path unless relative path already matches
|
||||
if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {
|
||||
if (cwd) path = sysPath.join(cwd, path);
|
||||
path = sysPath.resolve(path);
|
||||
}
|
||||
|
||||
this._closePath(path);
|
||||
|
||||
this._ignoredPaths.add(path);
|
||||
if (this._watched.has(path)) {
|
||||
this._ignoredPaths.add(path + SLASH_GLOBSTAR);
|
||||
}
|
||||
|
||||
// reset the cached userIgnored anymatch fn
|
||||
// to make ignoredPaths changes effective
|
||||
this._userIgnored = undefined;
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close watchers and remove all listeners from watched paths.
|
||||
* @returns {Promise<void>}.
|
||||
*/
|
||||
close() {
|
||||
if (this.closed) return this._closePromise;
|
||||
this.closed = true;
|
||||
|
||||
// Memory management.
|
||||
this.removeAllListeners();
|
||||
const closers = [];
|
||||
this._closers.forEach(closerList => closerList.forEach(closer => {
|
||||
const promise = closer();
|
||||
if (promise instanceof Promise) closers.push(promise);
|
||||
}));
|
||||
this._streams.forEach(stream => stream.destroy());
|
||||
this._userIgnored = undefined;
|
||||
this._readyCount = 0;
|
||||
this._readyEmitted = false;
|
||||
this._watched.forEach(dirent => dirent.dispose());
|
||||
['closers', 'watched', 'streams', 'symlinkPaths', 'throttled'].forEach(key => {
|
||||
this[`_${key}`].clear();
|
||||
});
|
||||
|
||||
this._closePromise = closers.length ? Promise.all(closers).then(() => undefined) : Promise.resolve();
|
||||
return this._closePromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose list of watched paths
|
||||
* @returns {Object} for chaining
|
||||
*/
|
||||
getWatched() {
|
||||
const watchList = {};
|
||||
this._watched.forEach((entry, dir) => {
|
||||
const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;
|
||||
watchList[key || ONE_DOT] = entry.getChildren().sort();
|
||||
});
|
||||
return watchList;
|
||||
}
|
||||
|
||||
emitWithAll(event, args) {
|
||||
this.emit(...args);
|
||||
if (event !== EV_ERROR) this.emit(EV_ALL, ...args);
|
||||
}
|
||||
|
||||
// Common helpers
|
||||
// --------------
|
||||
|
||||
/**
|
||||
* Normalize and emit events.
|
||||
* Calling _emit DOES NOT MEAN emit() would be called!
|
||||
* @param {EventName} event Type of event
|
||||
* @param {Path} path File or directory path
|
||||
* @param {*=} val1 arguments to be passed with event
|
||||
* @param {*=} val2
|
||||
* @param {*=} val3
|
||||
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
||||
*/
|
||||
async _emit(event, path, val1, val2, val3) {
|
||||
if (this.closed) return;
|
||||
|
||||
const opts = this.options;
|
||||
if (isWindows) path = sysPath.normalize(path);
|
||||
if (opts.cwd) path = sysPath.relative(opts.cwd, path);
|
||||
/** @type Array<any> */
|
||||
const args = [event, path];
|
||||
if (val3 !== undefined) args.push(val1, val2, val3);
|
||||
else if (val2 !== undefined) args.push(val1, val2);
|
||||
else if (val1 !== undefined) args.push(val1);
|
||||
|
||||
const awf = opts.awaitWriteFinish;
|
||||
let pw;
|
||||
if (awf && (pw = this._pendingWrites.get(path))) {
|
||||
pw.lastChange = new Date();
|
||||
return this;
|
||||
}
|
||||
|
||||
if (opts.atomic) {
|
||||
if (event === EV_UNLINK) {
|
||||
this._pendingUnlinks.set(path, args);
|
||||
setTimeout(() => {
|
||||
this._pendingUnlinks.forEach((entry, path) => {
|
||||
this.emit(...entry);
|
||||
this.emit(EV_ALL, ...entry);
|
||||
this._pendingUnlinks.delete(path);
|
||||
});
|
||||
}, typeof opts.atomic === 'number' ? opts.atomic : 100);
|
||||
return this;
|
||||
}
|
||||
if (event === EV_ADD && this._pendingUnlinks.has(path)) {
|
||||
event = args[0] = EV_CHANGE;
|
||||
this._pendingUnlinks.delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (awf && (event === EV_ADD || event === EV_CHANGE) && this._readyEmitted) {
|
||||
const awfEmit = (err, stats) => {
|
||||
if (err) {
|
||||
event = args[0] = EV_ERROR;
|
||||
args[1] = err;
|
||||
this.emitWithAll(event, args);
|
||||
} else if (stats) {
|
||||
// if stats doesn't exist the file must have been deleted
|
||||
if (args.length > 2) {
|
||||
args[2] = stats;
|
||||
} else {
|
||||
args.push(stats);
|
||||
}
|
||||
this.emitWithAll(event, args);
|
||||
}
|
||||
};
|
||||
|
||||
this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (event === EV_CHANGE) {
|
||||
const isThrottled = !this._throttle(EV_CHANGE, path, 50);
|
||||
if (isThrottled) return this;
|
||||
}
|
||||
|
||||
if (opts.alwaysStat && val1 === undefined &&
|
||||
(event === EV_ADD || event === EV_ADD_DIR || event === EV_CHANGE)
|
||||
) {
|
||||
const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;
|
||||
let stats;
|
||||
try {
|
||||
stats = await stat(fullPath);
|
||||
} catch (err) {}
|
||||
// Suppress event when fs_stat fails, to avoid sending undefined 'stat'
|
||||
if (!stats || this.closed) return;
|
||||
args.push(stats);
|
||||
}
|
||||
this.emitWithAll(event, args);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common handler for errors
|
||||
* @param {Error} error
|
||||
* @returns {Error|Boolean} The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
||||
*/
|
||||
_handleError(error) {
|
||||
const code = error && error.code;
|
||||
if (error && code !== 'ENOENT' && code !== 'ENOTDIR' &&
|
||||
(!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))
|
||||
) {
|
||||
this.emit(EV_ERROR, error);
|
||||
}
|
||||
return error || this.closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper utility for throttling
|
||||
* @param {ThrottleType} actionType type being throttled
|
||||
* @param {Path} path being acted upon
|
||||
* @param {Number} timeout duration of time to suppress duplicate actions
|
||||
* @returns {Object|false} tracking object or false if action should be suppressed
|
||||
*/
|
||||
_throttle(actionType, path, timeout) {
|
||||
if (!this._throttled.has(actionType)) {
|
||||
this._throttled.set(actionType, new Map());
|
||||
}
|
||||
|
||||
/** @type {Map<Path, Object>} */
|
||||
const action = this._throttled.get(actionType);
|
||||
/** @type {Object} */
|
||||
const actionPath = action.get(path);
|
||||
|
||||
if (actionPath) {
|
||||
actionPath.count++;
|
||||
return false;
|
||||
}
|
||||
|
||||
let timeoutObject;
|
||||
const clear = () => {
|
||||
const item = action.get(path);
|
||||
const count = item ? item.count : 0;
|
||||
action.delete(path);
|
||||
clearTimeout(timeoutObject);
|
||||
if (item) clearTimeout(item.timeoutObject);
|
||||
return count;
|
||||
};
|
||||
timeoutObject = setTimeout(clear, timeout);
|
||||
const thr = {timeoutObject, clear, count: 0};
|
||||
action.set(path, thr);
|
||||
return thr;
|
||||
}
|
||||
|
||||
_incrReadyCount() {
|
||||
return this._readyCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Awaits write operation to finish.
|
||||
* Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
|
||||
* @param {Path} path being acted upon
|
||||
* @param {Number} threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
|
||||
* @param {EventName} event
|
||||
* @param {Function} awfEmit Callback to be called when ready for event to be emitted.
|
||||
*/
|
||||
_awaitWriteFinish(path, threshold, event, awfEmit) {
|
||||
let timeoutHandler;
|
||||
|
||||
let fullPath = path;
|
||||
if (this.options.cwd && !sysPath.isAbsolute(path)) {
|
||||
fullPath = sysPath.join(this.options.cwd, path);
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
|
||||
const awaitWriteFinish = (prevStat) => {
|
||||
fs.stat(fullPath, (err, curStat) => {
|
||||
if (err || !this._pendingWrites.has(path)) {
|
||||
if (err && err.code !== 'ENOENT') awfEmit(err);
|
||||
return;
|
||||
}
|
||||
|
||||
const now = Number(new Date());
|
||||
|
||||
if (prevStat && curStat.size !== prevStat.size) {
|
||||
this._pendingWrites.get(path).lastChange = now;
|
||||
}
|
||||
const pw = this._pendingWrites.get(path);
|
||||
const df = now - pw.lastChange;
|
||||
|
||||
if (df >= threshold) {
|
||||
this._pendingWrites.delete(path);
|
||||
awfEmit(undefined, curStat);
|
||||
} else {
|
||||
timeoutHandler = setTimeout(
|
||||
awaitWriteFinish,
|
||||
this.options.awaitWriteFinish.pollInterval,
|
||||
curStat
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (!this._pendingWrites.has(path)) {
|
||||
this._pendingWrites.set(path, {
|
||||
lastChange: now,
|
||||
cancelWait: () => {
|
||||
this._pendingWrites.delete(path);
|
||||
clearTimeout(timeoutHandler);
|
||||
return event;
|
||||
}
|
||||
});
|
||||
timeoutHandler = setTimeout(
|
||||
awaitWriteFinish,
|
||||
this.options.awaitWriteFinish.pollInterval
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_getGlobIgnored() {
|
||||
return [...this._ignoredPaths.values()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether user has asked to ignore this path.
|
||||
* @param {Path} path filepath or dir
|
||||
* @param {fs.Stats=} stats result of fs.stat
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
_isIgnored(path, stats) {
|
||||
if (this.options.atomic && DOT_RE.test(path)) return true;
|
||||
if (!this._userIgnored) {
|
||||
const {cwd} = this.options;
|
||||
const ign = this.options.ignored;
|
||||
|
||||
const ignored = ign && ign.map(normalizeIgnored(cwd));
|
||||
const paths = arrify(ignored)
|
||||
.filter((path) => typeof path === STRING_TYPE && !isGlob(path))
|
||||
.map((path) => path + SLASH_GLOBSTAR);
|
||||
const list = this._getGlobIgnored().map(normalizeIgnored(cwd)).concat(ignored, paths);
|
||||
this._userIgnored = anymatch(list, undefined, ANYMATCH_OPTS);
|
||||
}
|
||||
|
||||
return this._userIgnored([path, stats]);
|
||||
}
|
||||
|
||||
_isntIgnored(path, stat) {
|
||||
return !this._isIgnored(path, stat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a set of common helpers and properties relating to symlink and glob handling.
|
||||
* @param {Path} path file, directory, or glob pattern being watched
|
||||
* @param {Number=} depth at any depth > 0, this isn't a glob
|
||||
* @returns {WatchHelper} object containing helpers for this path
|
||||
*/
|
||||
_getWatchHelpers(path, depth) {
|
||||
const watchPath = depth || this.options.disableGlobbing || !isGlob(path) ? path : globParent(path);
|
||||
const follow = this.options.followSymlinks;
|
||||
|
||||
return new WatchHelper(path, watchPath, follow, this);
|
||||
}
|
||||
|
||||
// Directory helpers
|
||||
// -----------------
|
||||
|
||||
/**
|
||||
* Provides directory tracking objects
|
||||
* @param {String} directory path of the directory
|
||||
* @returns {DirEntry} the directory's tracking object
|
||||
*/
|
||||
_getWatchedDir(directory) {
|
||||
if (!this._boundRemove) this._boundRemove = this._remove.bind(this);
|
||||
const dir = sysPath.resolve(directory);
|
||||
if (!this._watched.has(dir)) this._watched.set(dir, new DirEntry(dir, this._boundRemove));
|
||||
return this._watched.get(dir);
|
||||
}
|
||||
|
||||
// File helpers
|
||||
// ------------
|
||||
|
||||
/**
|
||||
* Check for read permissions.
|
||||
* Based on this answer on SO: https://stackoverflow.com/a/11781404/1358405
|
||||
* @param {fs.Stats} stats - object, result of fs_stat
|
||||
* @returns {Boolean} indicates whether the file can be read
|
||||
*/
|
||||
_hasReadPermissions(stats) {
|
||||
if (this.options.ignorePermissionErrors) return true;
|
||||
|
||||
// stats.mode may be bigint
|
||||
const md = stats && Number.parseInt(stats.mode, 10);
|
||||
const st = md & 0o777;
|
||||
const it = Number.parseInt(st.toString(8)[0], 10);
|
||||
return Boolean(4 & it);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles emitting unlink events for
|
||||
* files and directories, and via recursion, for
|
||||
* files and directories within directories that are unlinked
|
||||
* @param {String} directory within which the following item is located
|
||||
* @param {String} item base path of item/directory
|
||||
* @returns {void}
|
||||
*/
|
||||
_remove(directory, item, isDirectory) {
|
||||
// if what is being deleted is a directory, get that directory's paths
|
||||
// for recursive deleting and cleaning of watched object
|
||||
// if it is not a directory, nestedDirectoryChildren will be empty array
|
||||
const path = sysPath.join(directory, item);
|
||||
const fullPath = sysPath.resolve(path);
|
||||
isDirectory = isDirectory != null
|
||||
? isDirectory
|
||||
: this._watched.has(path) || this._watched.has(fullPath);
|
||||
|
||||
// prevent duplicate handling in case of arriving here nearly simultaneously
|
||||
// via multiple paths (such as _handleFile and _handleDir)
|
||||
if (!this._throttle('remove', path, 100)) return;
|
||||
|
||||
// if the only watched file is removed, watch for its return
|
||||
if (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) {
|
||||
this.add(directory, item, true);
|
||||
}
|
||||
|
||||
// This will create a new entry in the watched object in either case
|
||||
// so we got to do the directory check beforehand
|
||||
const wp = this._getWatchedDir(path);
|
||||
const nestedDirectoryChildren = wp.getChildren();
|
||||
|
||||
// Recursively remove children directories / files.
|
||||
nestedDirectoryChildren.forEach(nested => this._remove(path, nested));
|
||||
|
||||
// Check if item was on the watched list and remove it
|
||||
const parent = this._getWatchedDir(directory);
|
||||
const wasTracked = parent.has(item);
|
||||
parent.remove(item);
|
||||
|
||||
// Fixes issue #1042 -> Relative paths were detected and added as symlinks
|
||||
// (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),
|
||||
// but never removed from the map in case the path was deleted.
|
||||
// This leads to an incorrect state if the path was recreated:
|
||||
// https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553
|
||||
if (this._symlinkPaths.has(fullPath)) {
|
||||
this._symlinkPaths.delete(fullPath);
|
||||
}
|
||||
|
||||
// If we wait for this file to be fully written, cancel the wait.
|
||||
let relPath = path;
|
||||
if (this.options.cwd) relPath = sysPath.relative(this.options.cwd, path);
|
||||
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
||||
const event = this._pendingWrites.get(relPath).cancelWait();
|
||||
if (event === EV_ADD) return;
|
||||
}
|
||||
|
||||
// The Entry will either be a directory that just got removed
|
||||
// or a bogus entry to a file, in either case we have to remove it
|
||||
this._watched.delete(path);
|
||||
this._watched.delete(fullPath);
|
||||
const eventName = isDirectory ? EV_UNLINK_DIR : EV_UNLINK;
|
||||
if (wasTracked && !this._isIgnored(path)) this._emit(eventName, path);
|
||||
|
||||
// Avoid conflicts if we later create another file with the same name
|
||||
if (!this.options.useFsEvents) {
|
||||
this._closePath(path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes all watchers for a path
|
||||
* @param {Path} path
|
||||
*/
|
||||
_closePath(path) {
|
||||
this._closeFile(path)
|
||||
const dir = sysPath.dirname(path);
|
||||
this._getWatchedDir(dir).remove(sysPath.basename(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes only file-specific watchers
|
||||
* @param {Path} path
|
||||
*/
|
||||
_closeFile(path) {
|
||||
const closers = this._closers.get(path);
|
||||
if (!closers) return;
|
||||
closers.forEach(closer => closer());
|
||||
this._closers.delete(path);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Path} path
|
||||
* @param {Function} closer
|
||||
*/
|
||||
_addPathCloser(path, closer) {
|
||||
if (!closer) return;
|
||||
let list = this._closers.get(path);
|
||||
if (!list) {
|
||||
list = [];
|
||||
this._closers.set(path, list);
|
||||
}
|
||||
list.push(closer);
|
||||
}
|
||||
|
||||
_readdirp(root, opts) {
|
||||
if (this.closed) return;
|
||||
const options = {type: EV_ALL, alwaysStat: true, lstat: true, ...opts};
|
||||
let stream = readdirp(root, options);
|
||||
this._streams.add(stream);
|
||||
stream.once(STR_CLOSE, () => {
|
||||
stream = undefined;
|
||||
});
|
||||
stream.once(STR_END, () => {
|
||||
if (stream) {
|
||||
this._streams.delete(stream);
|
||||
stream = undefined;
|
||||
}
|
||||
});
|
||||
return stream;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Export FSWatcher class
|
||||
exports.FSWatcher = FSWatcher;
|
||||
|
||||
/**
|
||||
* Instantiates watcher with paths to be tracked.
|
||||
* @param {String|Array<String>} paths file/directory paths and/or globs
|
||||
* @param {Object=} options chokidar opts
|
||||
* @returns an instance of FSWatcher for chaining.
|
||||
*/
|
||||
const watch = (paths, options) => {
|
||||
const watcher = new FSWatcher(options);
|
||||
watcher.add(paths);
|
||||
return watcher;
|
||||
};
|
||||
|
||||
exports.watch = watch;
|
||||
110
node_modules/chokidar/node_modules/glob-parent/CHANGELOG.md
generated
vendored
Normal file
110
node_modules/chokidar/node_modules/glob-parent/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
### [5.1.2](https://github.com/gulpjs/glob-parent/compare/v5.1.1...v5.1.2) (2021-03-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* eliminate ReDoS ([#36](https://github.com/gulpjs/glob-parent/issues/36)) ([f923116](https://github.com/gulpjs/glob-parent/commit/f9231168b0041fea3f8f954b3cceb56269fc6366))
|
||||
|
||||
### [5.1.1](https://github.com/gulpjs/glob-parent/compare/v5.1.0...v5.1.1) (2021-01-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* unescape exclamation mark ([#26](https://github.com/gulpjs/glob-parent/issues/26)) ([a98874f](https://github.com/gulpjs/glob-parent/commit/a98874f1a59e407f4fb1beb0db4efa8392da60bb))
|
||||
|
||||
## [5.1.0](https://github.com/gulpjs/glob-parent/compare/v5.0.0...v5.1.0) (2021-01-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add `flipBackslashes` option to disable auto conversion of slashes (closes [#24](https://github.com/gulpjs/glob-parent/issues/24)) ([#25](https://github.com/gulpjs/glob-parent/issues/25)) ([eecf91d](https://github.com/gulpjs/glob-parent/commit/eecf91d5e3834ed78aee39c4eaaae654d76b87b3))
|
||||
|
||||
## [5.0.0](https://github.com/gulpjs/glob-parent/compare/v4.0.0...v5.0.0) (2021-01-27)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* Drop support for node <6 & bump dependencies
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* Drop support for node <6 & bump dependencies ([896c0c0](https://github.com/gulpjs/glob-parent/commit/896c0c00b4e7362f60b96e7fc295ae929245255a))
|
||||
|
||||
## [4.0.0](https://github.com/gulpjs/glob-parent/compare/v3.1.0...v4.0.0) (2021-01-27)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* question marks are valid path characters on Windows so avoid flagging as a glob when alone
|
||||
* Update is-glob dependency
|
||||
|
||||
### Features
|
||||
|
||||
* hoist regexps and strings for performance gains ([4a80667](https://github.com/gulpjs/glob-parent/commit/4a80667c69355c76a572a5892b0f133c8e1f457e))
|
||||
* question marks are valid path characters on Windows so avoid flagging as a glob when alone ([2a551dd](https://github.com/gulpjs/glob-parent/commit/2a551dd0dc3235e78bf3c94843d4107072d17841))
|
||||
* Update is-glob dependency ([e41fcd8](https://github.com/gulpjs/glob-parent/commit/e41fcd895d1f7bc617dba45c9d935a7949b9c281))
|
||||
|
||||
## [3.1.0](https://github.com/gulpjs/glob-parent/compare/v3.0.1...v3.1.0) (2021-01-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* allow basic win32 backslash use ([272afa5](https://github.com/gulpjs/glob-parent/commit/272afa5fd070fc0f796386a5993d4ee4a846988b))
|
||||
* handle extglobs (parentheses) containing separators ([7db1bdb](https://github.com/gulpjs/glob-parent/commit/7db1bdb0756e55fd14619e8ce31aa31b17b117fd))
|
||||
* new approach to braces/brackets handling ([8269bd8](https://github.com/gulpjs/glob-parent/commit/8269bd89290d99fac9395a354fb56fdcdb80f0be))
|
||||
* pre-process braces/brackets sections ([9ef8a87](https://github.com/gulpjs/glob-parent/commit/9ef8a87f66b1a43d0591e7a8e4fc5a18415ee388))
|
||||
* preserve escaped brace/bracket at end of string ([8cfb0ba](https://github.com/gulpjs/glob-parent/commit/8cfb0ba84202d51571340dcbaf61b79d16a26c76))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* trailing escaped square brackets ([99ec9fe](https://github.com/gulpjs/glob-parent/commit/99ec9fecc60ee488ded20a94dd4f18b4f55c4ccf))
|
||||
|
||||
### [3.0.1](https://github.com/gulpjs/glob-parent/compare/v3.0.0...v3.0.1) (2021-01-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* use path-dirname ponyfill ([cdbea5f](https://github.com/gulpjs/glob-parent/commit/cdbea5f32a58a54e001a75ddd7c0fccd4776aacc))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* unescape glob-escaped dirnames on output ([598c533](https://github.com/gulpjs/glob-parent/commit/598c533bdf49c1428bc063aa9b8db40c5a86b030))
|
||||
|
||||
## [3.0.0](https://github.com/gulpjs/glob-parent/compare/v2.0.0...v3.0.0) (2021-01-27)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* update is-glob dependency
|
||||
|
||||
### Features
|
||||
|
||||
* update is-glob dependency ([5c5f8ef](https://github.com/gulpjs/glob-parent/commit/5c5f8efcee362a8e7638cf8220666acd8784f6bd))
|
||||
|
||||
## [2.0.0](https://github.com/gulpjs/glob-parent/compare/v1.3.0...v2.0.0) (2021-01-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* move up to dirname regardless of glob characters ([f97fb83](https://github.com/gulpjs/glob-parent/commit/f97fb83be2e0a9fc8d3b760e789d2ecadd6aa0c2))
|
||||
|
||||
## [1.3.0](https://github.com/gulpjs/glob-parent/compare/v1.2.0...v1.3.0) (2021-01-27)
|
||||
|
||||
## [1.2.0](https://github.com/gulpjs/glob-parent/compare/v1.1.0...v1.2.0) (2021-01-27)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* feat: make regex test strings smaller ([dc80fa9](https://github.com/gulpjs/glob-parent/commit/dc80fa9658dca20549cfeba44bbd37d5246fcce0))
|
||||
|
||||
## [1.1.0](https://github.com/gulpjs/glob-parent/compare/v1.0.0...v1.1.0) (2021-01-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* make regex test strings smaller ([cd83220](https://github.com/gulpjs/glob-parent/commit/cd832208638f45169f986d80fcf66e401f35d233))
|
||||
|
||||
## 1.0.0 (2021-01-27)
|
||||
|
||||
15
node_modules/chokidar/node_modules/glob-parent/LICENSE
generated
vendored
Normal file
15
node_modules/chokidar/node_modules/glob-parent/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
The ISC License
|
||||
|
||||
Copyright (c) 2015, 2019 Elan Shanker
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
137
node_modules/chokidar/node_modules/glob-parent/README.md
generated
vendored
Normal file
137
node_modules/chokidar/node_modules/glob-parent/README.md
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
<p align="center">
|
||||
<a href="https://gulpjs.com">
|
||||
<img height="257" width="114" src="https://raw.githubusercontent.com/gulpjs/artwork/master/gulp-2x.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
# glob-parent
|
||||
|
||||
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Azure Pipelines Build Status][azure-pipelines-image]][azure-pipelines-url] [![Travis Build Status][travis-image]][travis-url] [![AppVeyor Build Status][appveyor-image]][appveyor-url] [![Coveralls Status][coveralls-image]][coveralls-url] [![Gitter chat][gitter-image]][gitter-url]
|
||||
|
||||
Extract the non-magic parent path from a glob string.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var globParent = require('glob-parent');
|
||||
|
||||
globParent('path/to/*.js'); // 'path/to'
|
||||
globParent('/root/path/to/*.js'); // '/root/path/to'
|
||||
globParent('/*.js'); // '/'
|
||||
globParent('*.js'); // '.'
|
||||
globParent('**/*.js'); // '.'
|
||||
globParent('path/{to,from}'); // 'path'
|
||||
globParent('path/!(to|from)'); // 'path'
|
||||
globParent('path/?(to|from)'); // 'path'
|
||||
globParent('path/+(to|from)'); // 'path'
|
||||
globParent('path/*(to|from)'); // 'path'
|
||||
globParent('path/@(to|from)'); // 'path'
|
||||
globParent('path/**/*'); // 'path'
|
||||
|
||||
// if provided a non-glob path, returns the nearest dir
|
||||
globParent('path/foo/bar.js'); // 'path/foo'
|
||||
globParent('path/foo/'); // 'path/foo'
|
||||
globParent('path/foo'); // 'path' (see issue #3 for details)
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `globParent(maybeGlobString, [options])`
|
||||
|
||||
Takes a string and returns the part of the path before the glob begins. Be aware of Escaping rules and Limitations below.
|
||||
|
||||
#### options
|
||||
|
||||
```js
|
||||
{
|
||||
// Disables the automatic conversion of slashes for Windows
|
||||
flipBackslashes: true
|
||||
}
|
||||
```
|
||||
|
||||
## Escaping
|
||||
|
||||
The following characters have special significance in glob patterns and must be escaped if you want them to be treated as regular path characters:
|
||||
|
||||
- `?` (question mark) unless used as a path segment alone
|
||||
- `*` (asterisk)
|
||||
- `|` (pipe)
|
||||
- `(` (opening parenthesis)
|
||||
- `)` (closing parenthesis)
|
||||
- `{` (opening curly brace)
|
||||
- `}` (closing curly brace)
|
||||
- `[` (opening bracket)
|
||||
- `]` (closing bracket)
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
globParent('foo/[bar]/') // 'foo'
|
||||
globParent('foo/\\[bar]/') // 'foo/[bar]'
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
### Braces & Brackets
|
||||
This library attempts a quick and imperfect method of determining which path
|
||||
parts have glob magic without fully parsing/lexing the pattern. There are some
|
||||
advanced use cases that can trip it up, such as nested braces where the outer
|
||||
pair is escaped and the inner one contains a path separator. If you find
|
||||
yourself in the unlikely circumstance of being affected by this or need to
|
||||
ensure higher-fidelity glob handling in your library, it is recommended that you
|
||||
pre-process your input with [expand-braces] and/or [expand-brackets].
|
||||
|
||||
### Windows
|
||||
Backslashes are not valid path separators for globs. If a path with backslashes
|
||||
is provided anyway, for simple cases, glob-parent will replace the path
|
||||
separator for you and return the non-glob parent path (now with
|
||||
forward-slashes, which are still valid as Windows path separators).
|
||||
|
||||
This cannot be used in conjunction with escape characters.
|
||||
|
||||
```js
|
||||
// BAD
|
||||
globParent('C:\\Program Files \\(x86\\)\\*.ext') // 'C:/Program Files /(x86/)'
|
||||
|
||||
// GOOD
|
||||
globParent('C:/Program Files\\(x86\\)/*.ext') // 'C:/Program Files (x86)'
|
||||
```
|
||||
|
||||
If you are using escape characters for a pattern without path parts (i.e.
|
||||
relative to `cwd`), prefix with `./` to avoid confusing glob-parent.
|
||||
|
||||
```js
|
||||
// BAD
|
||||
globParent('foo \\[bar]') // 'foo '
|
||||
globParent('foo \\[bar]*') // 'foo '
|
||||
|
||||
// GOOD
|
||||
globParent('./foo \\[bar]') // 'foo [bar]'
|
||||
globParent('./foo \\[bar]*') // '.'
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
ISC
|
||||
|
||||
[expand-braces]: https://github.com/jonschlinkert/expand-braces
|
||||
[expand-brackets]: https://github.com/jonschlinkert/expand-brackets
|
||||
|
||||
[downloads-image]: https://img.shields.io/npm/dm/glob-parent.svg
|
||||
[npm-url]: https://www.npmjs.com/package/glob-parent
|
||||
[npm-image]: https://img.shields.io/npm/v/glob-parent.svg
|
||||
|
||||
[azure-pipelines-url]: https://dev.azure.com/gulpjs/gulp/_build/latest?definitionId=2&branchName=master
|
||||
[azure-pipelines-image]: https://dev.azure.com/gulpjs/gulp/_apis/build/status/glob-parent?branchName=master
|
||||
|
||||
[travis-url]: https://travis-ci.org/gulpjs/glob-parent
|
||||
[travis-image]: https://img.shields.io/travis/gulpjs/glob-parent.svg?label=travis-ci
|
||||
|
||||
[appveyor-url]: https://ci.appveyor.com/project/gulpjs/glob-parent
|
||||
[appveyor-image]: https://img.shields.io/appveyor/ci/gulpjs/glob-parent.svg?label=appveyor
|
||||
|
||||
[coveralls-url]: https://coveralls.io/r/gulpjs/glob-parent
|
||||
[coveralls-image]: https://img.shields.io/coveralls/gulpjs/glob-parent/master.svg
|
||||
|
||||
[gitter-url]: https://gitter.im/gulpjs/gulp
|
||||
[gitter-image]: https://badges.gitter.im/gulpjs/gulp.svg
|
||||
42
node_modules/chokidar/node_modules/glob-parent/index.js
generated
vendored
Normal file
42
node_modules/chokidar/node_modules/glob-parent/index.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
|
||||
var isGlob = require('is-glob');
|
||||
var pathPosixDirname = require('path').posix.dirname;
|
||||
var isWin32 = require('os').platform() === 'win32';
|
||||
|
||||
var slash = '/';
|
||||
var backslash = /\\/g;
|
||||
var enclosure = /[\{\[].*[\}\]]$/;
|
||||
var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/;
|
||||
var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g;
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @param {Object} opts
|
||||
* @param {boolean} [opts.flipBackslashes=true]
|
||||
* @returns {string}
|
||||
*/
|
||||
module.exports = function globParent(str, opts) {
|
||||
var options = Object.assign({ flipBackslashes: true }, opts);
|
||||
|
||||
// flip windows path separators
|
||||
if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) {
|
||||
str = str.replace(backslash, slash);
|
||||
}
|
||||
|
||||
// special case for strings ending in enclosure containing path separator
|
||||
if (enclosure.test(str)) {
|
||||
str += slash;
|
||||
}
|
||||
|
||||
// preserves full path in case of trailing path separator
|
||||
str += 'a';
|
||||
|
||||
// remove path parts that are globby
|
||||
do {
|
||||
str = pathPosixDirname(str);
|
||||
} while (isGlob(str) || globby.test(str));
|
||||
|
||||
// remove escape chars and return result
|
||||
return str.replace(escaped, '$1');
|
||||
};
|
||||
48
node_modules/chokidar/node_modules/glob-parent/package.json
generated
vendored
Normal file
48
node_modules/chokidar/node_modules/glob-parent/package.json
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "glob-parent",
|
||||
"version": "5.1.2",
|
||||
"description": "Extract the non-magic parent path from a glob string.",
|
||||
"author": "Gulp Team <team@gulpjs.com> (https://gulpjs.com/)",
|
||||
"contributors": [
|
||||
"Elan Shanker (https://github.com/es128)",
|
||||
"Blaine Bublitz <blaine.bublitz@gmail.com>"
|
||||
],
|
||||
"repository": "gulpjs/glob-parent",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"index.js"
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"pretest": "npm run lint",
|
||||
"test": "nyc mocha --async-only",
|
||||
"azure-pipelines": "nyc mocha --async-only --reporter xunit -O output=test.xunit",
|
||||
"coveralls": "nyc report --reporter=text-lcov | coveralls"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"coveralls": "^3.0.11",
|
||||
"eslint": "^2.13.1",
|
||||
"eslint-config-gulp": "^3.0.1",
|
||||
"expect": "^1.20.2",
|
||||
"mocha": "^6.0.2",
|
||||
"nyc": "^13.3.0"
|
||||
},
|
||||
"keywords": [
|
||||
"glob",
|
||||
"parent",
|
||||
"strip",
|
||||
"path",
|
||||
"dirname",
|
||||
"directory",
|
||||
"base",
|
||||
"wildcard"
|
||||
]
|
||||
}
|
||||
70
node_modules/chokidar/package.json
generated
vendored
Normal file
70
node_modules/chokidar/package.json
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "chokidar",
|
||||
"description": "Minimal and efficient cross-platform file watching library",
|
||||
"version": "3.6.0",
|
||||
"homepage": "https://github.com/paulmillr/chokidar",
|
||||
"author": "Paul Miller (https://paulmillr.com)",
|
||||
"contributors": [
|
||||
"Paul Miller (https://paulmillr.com)",
|
||||
"Elan Shanker"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"main": "index.js",
|
||||
"types": "./types/index.d.ts",
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14",
|
||||
"chai": "^4.3",
|
||||
"dtslint": "^3.3.0",
|
||||
"eslint": "^7.0.0",
|
||||
"mocha": "^7.0.0",
|
||||
"rimraf": "^3.0.0",
|
||||
"sinon": "^9.0.1",
|
||||
"sinon-chai": "^3.3.0",
|
||||
"typescript": "^4.4.3",
|
||||
"upath": "^1.2.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"lib/*.js",
|
||||
"types/index.d.ts"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/paulmillr/chokidar.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/paulmillr/chokidar/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dtslint": "dtslint types",
|
||||
"lint": "eslint --report-unused-disable-directives --ignore-path .gitignore .",
|
||||
"build": "npm ls",
|
||||
"mocha": "mocha --exit --timeout 90000",
|
||||
"test": "npm run lint && npm run mocha"
|
||||
},
|
||||
"keywords": [
|
||||
"fs",
|
||||
"watch",
|
||||
"watchFile",
|
||||
"watcher",
|
||||
"watching",
|
||||
"file",
|
||||
"fsevents"
|
||||
],
|
||||
"funding": "https://paulmillr.com/funding/"
|
||||
}
|
||||
192
node_modules/chokidar/types/index.d.ts
generated
vendored
Normal file
192
node_modules/chokidar/types/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
// TypeScript Version: 3.0
|
||||
|
||||
/// <reference types="node" />
|
||||
|
||||
import * as fs from "fs";
|
||||
import { EventEmitter } from "events";
|
||||
import { Matcher } from 'anymatch';
|
||||
|
||||
export class FSWatcher extends EventEmitter implements fs.FSWatcher {
|
||||
options: WatchOptions;
|
||||
|
||||
/**
|
||||
* Constructs a new FSWatcher instance with optional WatchOptions parameter.
|
||||
*/
|
||||
constructor(options?: WatchOptions);
|
||||
|
||||
/**
|
||||
* Add files, directories, or glob patterns for tracking. Takes an array of strings or just one
|
||||
* string.
|
||||
*/
|
||||
add(paths: string | ReadonlyArray<string>): this;
|
||||
|
||||
/**
|
||||
* Stop watching files, directories, or glob patterns. Takes an array of strings or just one
|
||||
* string.
|
||||
*/
|
||||
unwatch(paths: string | ReadonlyArray<string>): this;
|
||||
|
||||
/**
|
||||
* Returns an object representing all the paths on the file system being watched by this
|
||||
* `FSWatcher` instance. The object's keys are all the directories (using absolute paths unless
|
||||
* the `cwd` option was used), and the values are arrays of the names of the items contained in
|
||||
* each directory.
|
||||
*/
|
||||
getWatched(): {
|
||||
[directory: string]: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes all listeners from watched files.
|
||||
*/
|
||||
close(): Promise<void>;
|
||||
|
||||
on(event: 'add'|'addDir'|'change', listener: (path: string, stats?: fs.Stats) => void): this;
|
||||
|
||||
on(event: 'all', listener: (eventName: 'add'|'addDir'|'change'|'unlink'|'unlinkDir', path: string, stats?: fs.Stats) => void): this;
|
||||
|
||||
/**
|
||||
* Error occurred
|
||||
*/
|
||||
on(event: 'error', listener: (error: Error) => void): this;
|
||||
|
||||
/**
|
||||
* Exposes the native Node `fs.FSWatcher events`
|
||||
*/
|
||||
on(event: 'raw', listener: (eventName: string, path: string, details: any) => void): this;
|
||||
|
||||
/**
|
||||
* Fires when the initial scan is complete
|
||||
*/
|
||||
on(event: 'ready', listener: () => void): this;
|
||||
|
||||
on(event: 'unlink'|'unlinkDir', listener: (path: string) => void): this;
|
||||
|
||||
on(event: string, listener: (...args: any[]) => void): this;
|
||||
|
||||
ref(): this;
|
||||
|
||||
unref(): this;
|
||||
}
|
||||
|
||||
export interface WatchOptions {
|
||||
/**
|
||||
* Indicates whether the process should continue to run as long as files are being watched. If
|
||||
* set to `false` when using `fsevents` to watch, no more events will be emitted after `ready`,
|
||||
* even if the process continues to run.
|
||||
*/
|
||||
persistent?: boolean;
|
||||
|
||||
/**
|
||||
* ([anymatch](https://github.com/micromatch/anymatch)-compatible definition) Defines files/paths to
|
||||
* be ignored. The whole relative or absolute path is tested, not just filename. If a function
|
||||
* with two arguments is provided, it gets called twice per path - once with a single argument
|
||||
* (the path), second time with two arguments (the path and the
|
||||
* [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object of that path).
|
||||
*/
|
||||
ignored?: Matcher;
|
||||
|
||||
/**
|
||||
* If set to `false` then `add`/`addDir` events are also emitted for matching paths while
|
||||
* instantiating the watching as chokidar discovers these file paths (before the `ready` event).
|
||||
*/
|
||||
ignoreInitial?: boolean;
|
||||
|
||||
/**
|
||||
* When `false`, only the symlinks themselves will be watched for changes instead of following
|
||||
* the link references and bubbling events through the link's path.
|
||||
*/
|
||||
followSymlinks?: boolean;
|
||||
|
||||
/**
|
||||
* The base directory from which watch `paths` are to be derived. Paths emitted with events will
|
||||
* be relative to this.
|
||||
*/
|
||||
cwd?: string;
|
||||
|
||||
/**
|
||||
* If set to true then the strings passed to .watch() and .add() are treated as literal path
|
||||
* names, even if they look like globs. Default: false.
|
||||
*/
|
||||
disableGlobbing?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU
|
||||
* utilization, consider setting this to `false`. It is typically necessary to **set this to
|
||||
* `true` to successfully watch files over a network**, and it may be necessary to successfully
|
||||
* watch files in other non-standard situations. Setting to `true` explicitly on OS X overrides
|
||||
* the `useFsEvents` default.
|
||||
*/
|
||||
usePolling?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to use the `fsevents` watching interface if available. When set to `true` explicitly
|
||||
* and `fsevents` is available this supercedes the `usePolling` setting. When set to `false` on
|
||||
* OS X, `usePolling: true` becomes the default.
|
||||
*/
|
||||
useFsEvents?: boolean;
|
||||
|
||||
/**
|
||||
* If relying upon the [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object that
|
||||
* may get passed with `add`, `addDir`, and `change` events, set this to `true` to ensure it is
|
||||
* provided even in cases where it wasn't already available from the underlying watch events.
|
||||
*/
|
||||
alwaysStat?: boolean;
|
||||
|
||||
/**
|
||||
* If set, limits how many levels of subdirectories will be traversed.
|
||||
*/
|
||||
depth?: number;
|
||||
|
||||
/**
|
||||
* Interval of file system polling.
|
||||
*/
|
||||
interval?: number;
|
||||
|
||||
/**
|
||||
* Interval of file system polling for binary files. ([see list of binary extensions](https://gi
|
||||
* thub.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json))
|
||||
*/
|
||||
binaryInterval?: number;
|
||||
|
||||
/**
|
||||
* Indicates whether to watch files that don't have read permissions if possible. If watching
|
||||
* fails due to `EPERM` or `EACCES` with this set to `true`, the errors will be suppressed
|
||||
* silently.
|
||||
*/
|
||||
ignorePermissionErrors?: boolean;
|
||||
|
||||
/**
|
||||
* `true` if `useFsEvents` and `usePolling` are `false`). Automatically filters out artifacts
|
||||
* that occur when using editors that use "atomic writes" instead of writing directly to the
|
||||
* source file. If a file is re-added within 100 ms of being deleted, Chokidar emits a `change`
|
||||
* event rather than `unlink` then `add`. If the default of 100 ms does not work well for you,
|
||||
* you can override it by setting `atomic` to a custom value, in milliseconds.
|
||||
*/
|
||||
atomic?: boolean | number;
|
||||
|
||||
/**
|
||||
* can be set to an object in order to adjust timing params:
|
||||
*/
|
||||
awaitWriteFinish?: AwaitWriteFinishOptions | boolean;
|
||||
}
|
||||
|
||||
export interface AwaitWriteFinishOptions {
|
||||
/**
|
||||
* Amount of time in milliseconds for a file size to remain constant before emitting its event.
|
||||
*/
|
||||
stabilityThreshold?: number;
|
||||
|
||||
/**
|
||||
* File size polling interval.
|
||||
*/
|
||||
pollInterval?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* produces an instance of `FSWatcher`.
|
||||
*/
|
||||
export function watch(
|
||||
paths: string | ReadonlyArray<string>,
|
||||
options?: WatchOptions
|
||||
): FSWatcher;
|
||||
Reference in New Issue
Block a user