update, text, response
This commit is contained in:
317
node_modules/chokidar/CHANGELOG.md
generated
vendored
Normal file
317
node_modules/chokidar/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
# Chokidar 2.1.5 (Mar 22, 2019)
|
||||
* Revert 2.1.3 atomic writing changes.
|
||||
|
||||
# Chokidar 2.1.4 (Mar 22, 2019)
|
||||
* Improve TypeScript type definitions for `on` method.
|
||||
|
||||
# Chokidar 2.1.3 (Mar 22, 2019)
|
||||
* Improve atomic writes handling
|
||||
|
||||
# Chokidar 2.1.2 (Feb 18, 2019)
|
||||
* Add TypeScript type definitions
|
||||
* More fixes for accessTime behavior (#800)
|
||||
|
||||
# Chokidar 2.1.1 (Feb 8, 2019)
|
||||
* Handle simultaneous change of LastAccessTime and ModifiedTime (#793)
|
||||
|
||||
# Chokidar 2.1.0 (Feb 5, 2019)
|
||||
* Ignore accessTime updates caused by read operations (#762).
|
||||
* Updated dependencies. Removed `lodash.debounce`.
|
||||
|
||||
# Chokidar 2.0.4 (Jun 18, 2018)
|
||||
* Prevent watcher.close() from crashing (#730).
|
||||
|
||||
# Chokidar 2.0.3 (Mar 22, 2018)
|
||||
* Fixes an issue that using fd = 0 is not closed in case
|
||||
Windows is used and a `EPERM` error is triggered.
|
||||
|
||||
# Chokidar 2.0.2 (Feb 14, 2018)
|
||||
* Allow semver range updates for upath dependency
|
||||
|
||||
# Chokidar 2.0.1 (Feb 8, 2018)
|
||||
* Fix #668 glob issue on Windows when using `ignore` and `cwd`. Thanks @remy!
|
||||
* Fix #546 possible uncaught exception when using `awaitWriteFinish`.
|
||||
Thanks @dsagal!
|
||||
|
||||
# Chokidar 2.0.0 (Dec 29, 2017)
|
||||
* Breaking: Upgrade globbing dependencies which require globs to be more strict and always use POSIX-style slashes because Windows-style slashes are used as escape sequences
|
||||
* Update tests to work with upgraded globbing dependencies
|
||||
* Add ability to log FSEvents require error by setting `CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR` env
|
||||
* Fix for handling braces in globs
|
||||
* Add node 8 & 9 to CI configs
|
||||
* Allow node 0.10 failures on Windows
|
||||
|
||||
# Chokidar 1.7.0 (May 8, 2017)
|
||||
* Add `disableGlobbing` option
|
||||
* Add ability to force interval value by setting CHOKIDAR_INTERVAL env
|
||||
variable
|
||||
* Fix issue with `.close()` being called before `ready`
|
||||
|
||||
# Chokidar 1.6.0 (Jun 22, 2016)
|
||||
* Added ability for force `usePolling` mode by setting `CHOKIDAR_USEPOLLING`
|
||||
env variable
|
||||
|
||||
# Chokidar 1.5.2 (Jun 7, 2016)
|
||||
* Fix missing `addDir` events when using `cwd` and `alwaysStat` options
|
||||
* Fix missing `add` events for files within a renamed directory
|
||||
|
||||
# Chokidar 1.5.1 (May 20, 2016)
|
||||
* To help prevent exhaustion of FSEvents system limitations, consolidate watch
|
||||
instances to the common parent upon detection of separate watch instances on
|
||||
many siblings
|
||||
|
||||
# Chokidar 1.5.0 (May 10, 2016)
|
||||
* Make debounce delay setting used with `atomic: true` user-customizable
|
||||
* Fixes and improvements to `awaitWriteFinish` features
|
||||
|
||||
# Chokidar 1.4.3 (Feb 26, 2016)
|
||||
* Update async-each dependency to ^1.0.0
|
||||
|
||||
# Chokidar 1.4.2 (Dec 30, 2015)
|
||||
* Now correctly emitting `stats` with `awaitWriteFinish` option.
|
||||
|
||||
# Chokidar 1.4.1 (Dec 9, 2015)
|
||||
* The watcher could now be correctly subclassed with ES6 class syntax.
|
||||
|
||||
# Chokidar 1.4.0 (Dec 3, 2015)
|
||||
* Add `.getWatched()` method, exposing all file system entries being watched
|
||||
* Apply `awaitWriteFinish` methodology to `change` events (in addition to `add`)
|
||||
* Fix handling of symlinks within glob paths (#293)
|
||||
* Fix `addDir` and `unlinkDir` events under globs (#337, #401)
|
||||
* Fix issues with `.unwatch()` (#374, #403)
|
||||
|
||||
# Chokidar 1.3.0 (Nov 18, 2015)
|
||||
* Improve `awaitWriteFinish` option behavior
|
||||
* Fix some `cwd` option behavior on Windows
|
||||
* `awaitWriteFinish` and `cwd` are now compatible
|
||||
* Fix some race conditions.
|
||||
* #379: Recreating deleted directory doesn't trigger event
|
||||
* When adding a previously-deleted file, emit 'add', not 'change'
|
||||
|
||||
# Chokidar 1.2.0 (Oct 1, 2015)
|
||||
* Allow nested arrays of paths to be provided to `.watch()` and `.add()`
|
||||
* Add `awaitWriteFinish` option
|
||||
|
||||
# Chokidar 1.1.0 (Sep 23, 2015)
|
||||
* Dependency updates including fsevents@1.0.0, improving installation
|
||||
|
||||
# Chokidar 1.0.6 (Sep 18, 2015)
|
||||
* Fix issue with `.unwatch()` method and relative paths
|
||||
|
||||
# Chokidar 1.0.5 (Jul 20, 2015)
|
||||
* Fix regression with regexes/fns using in `ignored`
|
||||
|
||||
# Chokidar 1.0.4 (Jul 15, 2015)
|
||||
* Fix bug with `ignored` files/globs while `cwd` option is set
|
||||
|
||||
# Chokidar 1.0.3 (Jun 4, 2015)
|
||||
* Fix race issue with `alwaysStat` option and removed files
|
||||
|
||||
# Chokidar 1.0.2 (May 30, 2015)
|
||||
* Fix bug with absolute paths and ENAMETOOLONG error
|
||||
|
||||
# Chokidar 1.0.1 (Apr 8, 2015)
|
||||
* Fix bug with `.close()` method in `fs.watch` mode with `persistent: false`
|
||||
option
|
||||
|
||||
# Chokidar 1.0.0 (Apr 7, 2015)
|
||||
* Glob support! Use globs in `watch`, `add`, and `unwatch` methods
|
||||
* Comprehensive symlink support
|
||||
* New `unwatch` method to turn off watching of previously watched paths
|
||||
* More flexible `ignored` option allowing regex, function, glob, or array
|
||||
courtesy of [anymatch](https://github.com/es128/anymatch)
|
||||
* New `cwd` option to set base dir from which relative paths are derived
|
||||
* New `depth` option for limiting recursion
|
||||
* New `alwaysStat` option to ensure
|
||||
[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) gets passed
|
||||
with every add/change event
|
||||
* New `ready` event emitted when initial fs tree scan is done and watcher is
|
||||
ready for changes
|
||||
* New `raw` event exposing data and events from the lower-level watch modules
|
||||
* New `followSymlinks` option to impact whether symlinks' targets or the symlink
|
||||
files themselves are watched
|
||||
* New `atomic` option for normalizing artifacts from text editors that use
|
||||
atomic write methods
|
||||
* Ensured watcher's stability with lots of bugfixes.
|
||||
|
||||
# Chokidar 0.12.6 (Jan 6, 2015)
|
||||
* Fix bug which breaks `persistent: false` mode when change events occur
|
||||
|
||||
# Chokidar 0.12.5 (Dec 17, 2014)
|
||||
* Fix bug with matching parent path detection for fsevents instance sharing
|
||||
* Fix bug with ignored watch path in nodefs modes
|
||||
|
||||
# Chokidar 0.12.4 (Dec 14, 2014)
|
||||
* Fix bug in `fs.watch` mode that caused watcher to leak into `cwd`
|
||||
* Fix bug preventing ready event when there are symlinks to ignored paths
|
||||
|
||||
# Chokidar 0.12.3 (Dec 13, 2014)
|
||||
* Fix handling of special files such as named pipes and sockets
|
||||
|
||||
# Chokidar 0.12.2 (Dec 12, 2014)
|
||||
* Fix recursive symlink handling and some other path resolution problems
|
||||
|
||||
# Chokidar 0.12.1 (Dec 10, 2014)
|
||||
* Fix a case where file symlinks were not followed properly
|
||||
|
||||
# Chokidar 0.12.0 (Dec 8, 2014)
|
||||
* Symlink support
|
||||
* Add `followSymlinks` option, which defaults to `true`
|
||||
* Change default watch mode on Linux to non-polling `fs.watch`
|
||||
* Add `atomic` option to normalize events from editors using atomic writes
|
||||
* Particularly Vim and Sublime
|
||||
* Add `raw` event which exposes data from the underlying watch method
|
||||
|
||||
# Chokidar 0.11.1 (Nov 19, 2014)
|
||||
* Fix a bug where an error is thrown when `fs.watch` instantiation fails
|
||||
|
||||
# Chokidar 0.11.0 (Nov 16, 2014)
|
||||
* Add a `ready` event, which is emitted after initial file scan completes
|
||||
* Fix issue with options keys passed in defined as `undefined`
|
||||
* Rename some internal `FSWatcher` properties to indicate they're private
|
||||
|
||||
# Chokidar 0.10.9 (Nov 15, 2014)
|
||||
* Fix some leftover issues from adding watcher reuse
|
||||
|
||||
# Chokidar 0.10.8 (Nov 14, 2014)
|
||||
* Remove accidentally committed/published `console.log` statement.
|
||||
* Sry 'bout that :crying_cat_face:
|
||||
|
||||
# Chokidar 0.10.7 (Nov 14, 2014)
|
||||
* Apply watcher reuse methodology to `fs.watch` and `fs.watchFile` as well
|
||||
|
||||
# Chokidar 0.10.6 (Nov 12, 2014)
|
||||
* More efficient creation/reuse of FSEvents instances to avoid system limits
|
||||
* Reduce simultaneous FSEvents instances allowed in a process
|
||||
* Handle errors thrown by `fs.watch` upon invocation
|
||||
|
||||
# Chokidar 0.10.5 (Nov 6, 2014)
|
||||
* Limit number of simultaneous FSEvents instances (fall back to other methods)
|
||||
* Prevent some cases of EMFILE errors during initialization
|
||||
* Fix ignored files emitting events in some fsevents-mode circumstances
|
||||
|
||||
# Chokidar 0.10.4 (Nov 5, 2014)
|
||||
* Bump fsevents dependency to ~0.3.1
|
||||
* Should resolve build warnings and `npm rebuild` on non-Macs
|
||||
|
||||
# Chokidar 0.10.3 (Oct 28, 2014)
|
||||
* Fix removed dir emitting as `unlink` instead of `unlinkDir`
|
||||
* Fix issues with file changing to dir or vice versa (gh-165)
|
||||
* Fix handling of `ignored` option in fsevents mode
|
||||
|
||||
# Chokidar 0.10.2 (Oct 23, 2014)
|
||||
* Improve individual file watching
|
||||
* Fix fsevents keeping process alive when `persistent: false`
|
||||
|
||||
# Chokidar 0.10.1 (19 October 2014)
|
||||
* Improve handling of text editor atomic writes
|
||||
|
||||
# Chokidar 0.10.0 (Oct 18, 2014)
|
||||
* Many stability and consistency improvements
|
||||
* Resolve many cases of duplicate or wrong events
|
||||
* Correct for fsevents inconsistencies
|
||||
* Standardize handling of errors and relative paths
|
||||
* Fix issues with watching `./`
|
||||
|
||||
# Chokidar 0.9.0 (Sep 25, 2014)
|
||||
* Updated fsevents to 0.3
|
||||
* Update per-system defaults
|
||||
* Fix issues with closing chokidar instance
|
||||
* Fix duplicate change events on win32
|
||||
|
||||
# Chokidar 0.8.2 (Mar 26, 2014)
|
||||
* Fixed npm issues related to fsevents dep.
|
||||
* Updated fsevents to 0.2.
|
||||
|
||||
# Chokidar 0.8.1 (Dec 16, 2013)
|
||||
* Optional deps are now truly optional on windows and
|
||||
linux.
|
||||
* Rewritten in JS, again.
|
||||
* Fixed some FSEvents-related bugs.
|
||||
|
||||
# Chokidar 0.8.0 (Nov 29, 2013)
|
||||
* Added ultra-fast low-CPU OS X file watching with FSEvents.
|
||||
It is enabled by default.
|
||||
* Added `addDir` and `unlinkDir` events.
|
||||
* Polling is now disabled by default on all platforms.
|
||||
|
||||
# Chokidar 0.7.1 (Nov 18, 2013)
|
||||
* `Watcher#close` now also removes all event listeners.
|
||||
|
||||
# Chokidar 0.7.0 (Oct 22, 2013)
|
||||
* When `options.ignored` is two-argument function, it will
|
||||
also be called after stating the FS, with `stats` argument.
|
||||
* `unlink` is no longer emitted on directories.
|
||||
|
||||
# Chokidar 0.6.3 (Aug 12, 2013)
|
||||
* Added `usePolling` option (default: `true`).
|
||||
When `false`, chokidar will use `fs.watch` as backend.
|
||||
`fs.watch` is much faster, but not like super reliable.
|
||||
|
||||
# Chokidar 0.6.2 (Mar 19, 2013)
|
||||
* Fixed watching initially empty directories with `ignoreInitial` option.
|
||||
|
||||
# Chokidar 0.6.1 (Mar 19, 2013)
|
||||
* Added node.js 0.10 support.
|
||||
|
||||
# Chokidar 0.6.0 (Mar 10, 2013)
|
||||
* File attributes (stat()) are now passed to `add` and `change` events as second
|
||||
arguments.
|
||||
* Changed default polling interval for binary files to 300ms.
|
||||
|
||||
# Chokidar 0.5.3 (Jan 13, 2013)
|
||||
* Removed emitting of `change` events before `unlink`.
|
||||
|
||||
# Chokidar 0.5.2 (Jan 13, 2013)
|
||||
* Removed postinstall script to prevent various npm bugs.
|
||||
|
||||
# Chokidar 0.5.1 (Jan 6, 2013)
|
||||
* When starting to watch non-existing paths, chokidar will no longer throw
|
||||
ENOENT error.
|
||||
* Fixed bug with absolute path.
|
||||
|
||||
# Chokidar 0.5.0 (Dec 9, 2012)
|
||||
* Added a bunch of new options:
|
||||
* `ignoreInitial` that allows to ignore initial `add` events.
|
||||
* `ignorePermissionErrors` that allows to ignore ENOENT etc perm errors.
|
||||
* `interval` and `binaryInterval` that allow to change default
|
||||
fs polling intervals.
|
||||
|
||||
# Chokidar 0.4.0 (Jul 26, 2012)
|
||||
* Added `all` event that receives two args (event name and path) that combines
|
||||
`add`, `change` and `unlink` events.
|
||||
* Switched to `fs.watchFile` on node.js 0.8 on windows.
|
||||
* Files are now correctly unwatched after unlink.
|
||||
|
||||
# Chokidar 0.3.0 (Jun 24, 2012)
|
||||
* `unlink` event are no longer emitted for directories, for consistency with
|
||||
`add`.
|
||||
|
||||
# Chokidar 0.2.6 (Jun 8, 2012)
|
||||
* Prevented creating of duplicate 'add' events.
|
||||
|
||||
# Chokidar 0.2.5 (Jun 8, 2012)
|
||||
* Fixed a bug when new files in new directories hadn't been added.
|
||||
|
||||
# Chokidar 0.2.4 (Jun 7, 2012)
|
||||
* Fixed a bug when unlinked files emitted events after unlink.
|
||||
|
||||
# Chokidar 0.2.3 (May 12, 2012)
|
||||
* Fixed watching of files on windows.
|
||||
|
||||
# Chokidar 0.2.2 (May 4, 2012)
|
||||
* Fixed watcher signature.
|
||||
|
||||
# Chokidar 0.2.1 (May 4, 2012)
|
||||
* Fixed invalid API bug when using `watch()`.
|
||||
|
||||
# Chokidar 0.2.0 (May 4, 2012)
|
||||
* Rewritten in js.
|
||||
|
||||
# Chokidar 0.1.1 (Apr 26, 2012)
|
||||
* Changed api to `chokidar.watch()`.
|
||||
* Fixed compilation on windows.
|
||||
|
||||
# Chokidar 0.1.0 (Apr 20, 2012)
|
||||
* Initial release, extracted from
|
||||
[Brunch](https://github.com/brunch/brunch/blob/9847a065aea300da99bd0753f90354cde9de1261/src/helpers.coffee#L66)
|
||||
21
node_modules/chokidar/LICENSE
generated
vendored
21
node_modules/chokidar/LICENSE
generated
vendored
@@ -1,21 +0,0 @@
|
||||
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.
|
||||
130
node_modules/chokidar/README.md
generated
vendored
130
node_modules/chokidar/README.md
generated
vendored
@@ -1,19 +1,18 @@
|
||||
# Chokidar [](https://github.com/paulmillr/chokidar) [](https://github.com/paulmillr/chokidar)
|
||||
# Chokidar [](https://github.com/paulmillr/chokidar) [](https://github.com/paulmillr/chokidar) [](https://travis-ci.org/paulmillr/chokidar) [](https://ci.appveyor.com/project/paulmillr/chokidar/branch/master) [](https://coveralls.io/r/paulmillr/chokidar)
|
||||
|
||||
> Minimal and efficient cross-platform file watching library
|
||||
> A neat wrapper around node.js fs.watch / fs.watchFile / FSEvents.
|
||||
|
||||
[](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`.
|
||||
* Has [a lot of other issues](https://github.com/nodejs/node/search?q=fs.watch&type=Issues)
|
||||
* Does not provide an easy way to recursively watch file trees.
|
||||
* Does not support recursive watching on Linux.
|
||||
|
||||
Node.js `fs.watchFile`:
|
||||
|
||||
@@ -23,21 +22,18 @@ Node.js `fs.watchFile`:
|
||||
|
||||
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),
|
||||
Initially made for **[Brunch](http://brunch.io)** (an ultra-swift web app build tool), it is now used in
|
||||
[gulp](https://github.com/gulpjs/gulp/),
|
||||
[karma](https://karma-runner.github.io/),
|
||||
[karma](http://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).
|
||||
[webpack](http://webpack.github.io/),
|
||||
[BrowserSync](http://www.browsersync.io/),
|
||||
[Microsoft's Visual Studio Code](https://github.com/microsoft/vscode),
|
||||
and [many others](https://www.npmjs.org/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.
|
||||
@@ -47,14 +43,13 @@ On MacOS, chokidar by default uses a native extension exposing the Darwin
|
||||
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
|
||||
On 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
|
||||
@@ -64,27 +59,25 @@ npm install chokidar
|
||||
Then `require` and use it in your code:
|
||||
|
||||
```javascript
|
||||
const chokidar = require('chokidar');
|
||||
var chokidar = require('chokidar');
|
||||
|
||||
// One-liner for current directory
|
||||
chokidar.watch('.').on('all', (event, path) => {
|
||||
// One-liner for current directory, ignores .dotfiles
|
||||
chokidar.watch('.', {ignored: /(^|[\/\\])\../}).on('all', (event, path) => {
|
||||
console.log(event, path);
|
||||
});
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```javascript
|
||||
// Example of a more typical implementation structure
|
||||
// Example of a more typical implementation structure:
|
||||
|
||||
// Initialize watcher.
|
||||
const watcher = chokidar.watch('file, dir, glob, or array', {
|
||||
ignored: /(^|[\/\\])\../, // ignore dotfiles
|
||||
var watcher = chokidar.watch('file, dir, glob, or array', {
|
||||
ignored: /(^|[\/\\])\../,
|
||||
persistent: true
|
||||
});
|
||||
|
||||
// Something to use when events are received.
|
||||
const log = console.log.bind(console);
|
||||
var log = console.log.bind(console);
|
||||
// Add event listeners.
|
||||
watcher
|
||||
.on('add', path => log(`File ${path} has been added`))
|
||||
@@ -97,12 +90,12 @@ watcher
|
||||
.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
|
||||
.on('raw', (event, path, details) => {
|
||||
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
|
||||
// argument when available: http://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}`);
|
||||
});
|
||||
@@ -115,14 +108,12 @@ watcher.add(['new-file-2', 'new-file-3', '**/other-file*']);
|
||||
var watchedPaths = watcher.getWatched();
|
||||
|
||||
// Un-watch some files.
|
||||
await watcher.unwatch('new-file*');
|
||||
watcher.unwatch('new-file*');
|
||||
|
||||
// Stop watching.
|
||||
// The method is async!
|
||||
watcher.close().then(() => console.log('closed'));
|
||||
watcher.close();
|
||||
|
||||
// Full list of options. See below for descriptions.
|
||||
// Do not use this example!
|
||||
// Full list of options. See below for descriptions. (do not use this example)
|
||||
chokidar.watch('file', {
|
||||
persistent: true,
|
||||
|
||||
@@ -132,7 +123,7 @@ chokidar.watch('file', {
|
||||
cwd: '.',
|
||||
disableGlobbing: false,
|
||||
|
||||
usePolling: false,
|
||||
usePolling: true,
|
||||
interval: 100,
|
||||
binaryInterval: 300,
|
||||
alwaysStat: false,
|
||||
@@ -148,15 +139,12 @@ chokidar.watch('file', {
|
||||
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
`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
|
||||
@@ -173,7 +161,7 @@ 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)
|
||||
[`fs.Stats`](http://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).
|
||||
@@ -196,7 +184,7 @@ 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
|
||||
* `interval` (default: `100`). Interval of file system polling. You may also
|
||||
set the CHOKIDAR_INTERVAL env variable to override this option.
|
||||
* `binaryInterval` (default: `300`). Interval of file system
|
||||
polling for binary files.
|
||||
@@ -206,7 +194,7 @@ to true (1) or false (0) in order to override this option.
|
||||
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)
|
||||
[`fs.Stats`](http://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.
|
||||
@@ -228,10 +216,9 @@ Use with caution.
|
||||
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.
|
||||
* `awaitWriteFinish.pollInterval` (default: 100). File size polling interval.
|
||||
|
||||
#### 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.
|
||||
@@ -253,10 +240,10 @@ Takes an array of strings or just one string.
|
||||
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.
|
||||
name and path for every event other than `ready`, `raw`, and `error`.
|
||||
* `.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.
|
||||
* `.close()`: Removes all listeners from watched files.
|
||||
* `.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
|
||||
@@ -265,7 +252,7 @@ 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
|
||||
[chokidar-cli](https://github.com/kimmobrunfeldt/chokidar-cli), allowing you to
|
||||
execute a command on each change, or get a stdio stream of change events.
|
||||
|
||||
## Install Troubleshooting
|
||||
@@ -275,34 +262,33 @@ execute a command on each change, or get a stdio stream of change events.
|
||||
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.
|
||||
* `ERR! stack Error: Python executable "python" is v3.4.1, which is not supported by gyp.`
|
||||
* You should be able to resolve this by installing python 2.7 and running:
|
||||
`npm config set python python2.7`
|
||||
|
||||
* 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).
|
||||
* `gyp ERR! stack Error: not found: make`
|
||||
* On Mac, install the XCode command-line tools
|
||||
|
||||
## License
|
||||
|
||||
MIT (c) Paul Miller (<https://paulmillr.com>), see [LICENSE](LICENSE) file.
|
||||
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.
|
||||
|
||||
1340
node_modules/chokidar/index.js
generated
vendored
1340
node_modules/chokidar/index.js
generated
vendored
File diff suppressed because it is too large
Load Diff
65
node_modules/chokidar/lib/constants.js
generated
vendored
65
node_modules/chokidar/lib/constants.js
generated
vendored
@@ -1,65 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const {sep} = require('path');
|
||||
const {platform} = process;
|
||||
const os = require('os');
|
||||
|
||||
exports.EV_ALL = 'all';
|
||||
exports.EV_READY = 'ready';
|
||||
exports.EV_ADD = 'add';
|
||||
exports.EV_CHANGE = 'change';
|
||||
exports.EV_ADD_DIR = 'addDir';
|
||||
exports.EV_UNLINK = 'unlink';
|
||||
exports.EV_UNLINK_DIR = 'unlinkDir';
|
||||
exports.EV_RAW = 'raw';
|
||||
exports.EV_ERROR = 'error';
|
||||
|
||||
exports.STR_DATA = 'data';
|
||||
exports.STR_END = 'end';
|
||||
exports.STR_CLOSE = 'close';
|
||||
|
||||
exports.FSEVENT_CREATED = 'created';
|
||||
exports.FSEVENT_MODIFIED = 'modified';
|
||||
exports.FSEVENT_DELETED = 'deleted';
|
||||
exports.FSEVENT_MOVED = 'moved';
|
||||
exports.FSEVENT_CLONED = 'cloned';
|
||||
exports.FSEVENT_UNKNOWN = 'unknown';
|
||||
exports.FSEVENT_TYPE_FILE = 'file';
|
||||
exports.FSEVENT_TYPE_DIRECTORY = 'directory';
|
||||
exports.FSEVENT_TYPE_SYMLINK = 'symlink';
|
||||
|
||||
exports.KEY_LISTENERS = 'listeners';
|
||||
exports.KEY_ERR = 'errHandlers';
|
||||
exports.KEY_RAW = 'rawEmitters';
|
||||
exports.HANDLER_KEYS = [exports.KEY_LISTENERS, exports.KEY_ERR, exports.KEY_RAW];
|
||||
|
||||
exports.DOT_SLASH = `.${sep}`;
|
||||
|
||||
exports.BACK_SLASH_RE = /\\/g;
|
||||
exports.DOUBLE_SLASH_RE = /\/\//;
|
||||
exports.SLASH_OR_BACK_SLASH_RE = /[/\\]/;
|
||||
exports.DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
|
||||
exports.REPLACER_RE = /^\.[/\\]/;
|
||||
|
||||
exports.SLASH = '/';
|
||||
exports.SLASH_SLASH = '//';
|
||||
exports.BRACE_START = '{';
|
||||
exports.BANG = '!';
|
||||
exports.ONE_DOT = '.';
|
||||
exports.TWO_DOTS = '..';
|
||||
exports.STAR = '*';
|
||||
exports.GLOBSTAR = '**';
|
||||
exports.ROOT_GLOBSTAR = '/**/*';
|
||||
exports.SLASH_GLOBSTAR = '/**';
|
||||
exports.DIR_SUFFIX = 'Dir';
|
||||
exports.ANYMATCH_OPTS = {dot: true};
|
||||
exports.STRING_TYPE = 'string';
|
||||
exports.FUNCTION_TYPE = 'function';
|
||||
exports.EMPTY_STR = '';
|
||||
exports.EMPTY_FN = () => {};
|
||||
exports.IDENTITY_FN = val => val;
|
||||
|
||||
exports.isWindows = platform === 'win32';
|
||||
exports.isMacos = platform === 'darwin';
|
||||
exports.isLinux = platform === 'linux';
|
||||
exports.isIBMi = os.type() === 'OS400';
|
||||
674
node_modules/chokidar/lib/fsevents-handler.js
generated
vendored
674
node_modules/chokidar/lib/fsevents-handler.js
generated
vendored
@@ -1,113 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const sysPath = require('path');
|
||||
const { promisify } = require('util');
|
||||
|
||||
let fsevents;
|
||||
try {
|
||||
fsevents = require('fsevents');
|
||||
} catch (error) {
|
||||
if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error);
|
||||
var fs = require('fs');
|
||||
var sysPath = require('path');
|
||||
var readdirp = require('readdirp');
|
||||
var fsevents;
|
||||
try { fsevents = require('fsevents'); } catch (error) {
|
||||
if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error)
|
||||
}
|
||||
|
||||
if (fsevents) {
|
||||
// TODO: real check
|
||||
const mtch = process.version.match(/v(\d+)\.(\d+)/);
|
||||
if (mtch && mtch[1] && mtch[2]) {
|
||||
const maj = Number.parseInt(mtch[1], 10);
|
||||
const min = Number.parseInt(mtch[2], 10);
|
||||
if (maj === 8 && min < 16) {
|
||||
fsevents = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
EV_ADD,
|
||||
EV_CHANGE,
|
||||
EV_ADD_DIR,
|
||||
EV_UNLINK,
|
||||
EV_ERROR,
|
||||
STR_DATA,
|
||||
STR_END,
|
||||
FSEVENT_CREATED,
|
||||
FSEVENT_MODIFIED,
|
||||
FSEVENT_DELETED,
|
||||
FSEVENT_MOVED,
|
||||
// FSEVENT_CLONED,
|
||||
FSEVENT_UNKNOWN,
|
||||
FSEVENT_TYPE_FILE,
|
||||
FSEVENT_TYPE_DIRECTORY,
|
||||
FSEVENT_TYPE_SYMLINK,
|
||||
|
||||
ROOT_GLOBSTAR,
|
||||
DIR_SUFFIX,
|
||||
DOT_SLASH,
|
||||
FUNCTION_TYPE,
|
||||
EMPTY_FN,
|
||||
IDENTITY_FN
|
||||
} = require('./constants');
|
||||
|
||||
const Depth = (value) => isNaN(value) ? {} : {depth: value};
|
||||
|
||||
const stat = promisify(fs.stat);
|
||||
const lstat = promisify(fs.lstat);
|
||||
const realpath = promisify(fs.realpath);
|
||||
|
||||
const statMethods = { stat, lstat };
|
||||
|
||||
/**
|
||||
* @typedef {String} Path
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} FsEventsWatchContainer
|
||||
* @property {Set<Function>} listeners
|
||||
* @property {Function} rawEmitter
|
||||
* @property {{stop: Function}} watcher
|
||||
*/
|
||||
|
||||
// fsevents instance helper functions
|
||||
/**
|
||||
* Object to hold per-process fsevents instances (may be shared across chokidar FSWatcher instances)
|
||||
* @type {Map<Path,FsEventsWatchContainer>}
|
||||
*/
|
||||
const FSEventsWatchers = new Map();
|
||||
|
||||
// object to hold per-process fsevents instances
|
||||
// (may be shared across chokidar FSWatcher instances)
|
||||
var FSEventsWatchers = Object.create(null);
|
||||
|
||||
// Threshold of duplicate path prefixes at which to start
|
||||
// consolidating going forward
|
||||
const consolidateThreshhold = 10;
|
||||
var consolidateThreshhold = 10;
|
||||
|
||||
const wrongEventFlags = new Set([
|
||||
69888, 70400, 71424, 72704, 73472, 131328, 131840, 262912
|
||||
]);
|
||||
// Private function: Instantiates the fsevents interface
|
||||
|
||||
/**
|
||||
* Instantiates the fsevents interface
|
||||
* @param {Path} path path to be watched
|
||||
* @param {Function} callback called when fsevents is bound and ready
|
||||
* @returns {{stop: Function}} new fsevents instance
|
||||
*/
|
||||
const createFSEventsInstance = (path, callback) => {
|
||||
const stop = fsevents.watch(path, callback);
|
||||
return {stop};
|
||||
};
|
||||
// * path - string, path to be watched
|
||||
// * callback - function, called when fsevents is bound and ready
|
||||
|
||||
/**
|
||||
* Instantiates the fsevents interface or binds listeners to an existing one covering
|
||||
* the same file tree.
|
||||
* @param {Path} path - to be watched
|
||||
* @param {Path} realPath - real path for symlinks
|
||||
* @param {Function} listener - called when fsevents emits events
|
||||
* @param {Function} rawEmitter - passes data to listeners of the 'raw' event
|
||||
* @returns {Function} closer
|
||||
*/
|
||||
// Returns new fsevents instance
|
||||
function createFSEventsInstance(path, callback) {
|
||||
return (new fsevents(path)).on('fsevent', callback).start();
|
||||
}
|
||||
|
||||
// Private function: Instantiates the fsevents interface or binds listeners
|
||||
// to an existing one covering the same file tree
|
||||
|
||||
// * path - string, path to be watched
|
||||
// * realPath - string, real path (in case of symlinks)
|
||||
// * listener - function, called when fsevents emits events
|
||||
// * rawEmitter - function, passes data to listeners of the 'raw' event
|
||||
|
||||
// Returns close function
|
||||
function setFSEventsListener(path, realPath, listener, rawEmitter) {
|
||||
let watchPath = sysPath.extname(realPath) ? sysPath.dirname(realPath) : realPath;
|
||||
|
||||
const parentPath = sysPath.dirname(watchPath);
|
||||
let cont = FSEventsWatchers.get(watchPath);
|
||||
var watchPath = sysPath.extname(path) ? sysPath.dirname(path) : path;
|
||||
var watchContainer;
|
||||
var parentPath = sysPath.dirname(watchPath);
|
||||
|
||||
// If we've accumulated a substantial number of paths that
|
||||
// could have been consolidated by watching one directory
|
||||
@@ -117,69 +50,68 @@ function setFSEventsListener(path, realPath, listener, rawEmitter) {
|
||||
watchPath = parentPath;
|
||||
}
|
||||
|
||||
const resolvedPath = sysPath.resolve(path);
|
||||
const hasSymlink = resolvedPath !== realPath;
|
||||
|
||||
const filteredListener = (fullPath, flags, info) => {
|
||||
var resolvedPath = sysPath.resolve(path);
|
||||
var hasSymlink = resolvedPath !== realPath;
|
||||
function filteredListener(fullPath, flags, info) {
|
||||
if (hasSymlink) fullPath = fullPath.replace(realPath, resolvedPath);
|
||||
if (
|
||||
fullPath === resolvedPath ||
|
||||
!fullPath.indexOf(resolvedPath + sysPath.sep)
|
||||
) listener(fullPath, flags, info);
|
||||
};
|
||||
}
|
||||
|
||||
// check if there is already a watcher on a parent path
|
||||
// modifies `watchPath` to the parent path when it finds a match
|
||||
let watchedParent = false;
|
||||
for (const watchedPath of FSEventsWatchers.keys()) {
|
||||
if (realPath.indexOf(sysPath.resolve(watchedPath) + sysPath.sep) === 0) {
|
||||
watchPath = watchedPath;
|
||||
cont = FSEventsWatchers.get(watchPath);
|
||||
watchedParent = true;
|
||||
break;
|
||||
}
|
||||
function watchedParent() {
|
||||
return Object.keys(FSEventsWatchers).some(function(watchedPath) {
|
||||
// condition is met when indexOf returns 0
|
||||
if (!realPath.indexOf(sysPath.resolve(watchedPath) + sysPath.sep)) {
|
||||
watchPath = watchedPath;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (cont || watchedParent) {
|
||||
cont.listeners.add(filteredListener);
|
||||
if (watchPath in FSEventsWatchers || watchedParent()) {
|
||||
watchContainer = FSEventsWatchers[watchPath];
|
||||
watchContainer.listeners.push(filteredListener);
|
||||
} else {
|
||||
cont = {
|
||||
listeners: new Set([filteredListener]),
|
||||
rawEmitter,
|
||||
watcher: createFSEventsInstance(watchPath, (fullPath, flags) => {
|
||||
if (!cont.listeners.size) return;
|
||||
const info = fsevents.getInfo(fullPath, flags);
|
||||
cont.listeners.forEach(list => {
|
||||
list(fullPath, flags, info);
|
||||
watchContainer = FSEventsWatchers[watchPath] = {
|
||||
listeners: [filteredListener],
|
||||
rawEmitters: [rawEmitter],
|
||||
watcher: createFSEventsInstance(watchPath, function(fullPath, flags) {
|
||||
var info = fsevents.getInfo(fullPath, flags);
|
||||
watchContainer.listeners.forEach(function(listener) {
|
||||
listener(fullPath, flags, info);
|
||||
});
|
||||
watchContainer.rawEmitters.forEach(function(emitter) {
|
||||
emitter(info.event, fullPath, info);
|
||||
});
|
||||
|
||||
cont.rawEmitter(info.event, fullPath, info);
|
||||
})
|
||||
};
|
||||
FSEventsWatchers.set(watchPath, cont);
|
||||
}
|
||||
var listenerIndex = watchContainer.listeners.length - 1;
|
||||
|
||||
// removes this instance's listeners and closes the underlying fsevents
|
||||
// instance if there are no more listeners left
|
||||
return () => {
|
||||
const lst = cont.listeners;
|
||||
|
||||
lst.delete(filteredListener);
|
||||
if (!lst.size) {
|
||||
FSEventsWatchers.delete(watchPath);
|
||||
if (cont.watcher) return cont.watcher.stop().then(() => {
|
||||
cont.rawEmitter = cont.watcher = undefined;
|
||||
Object.freeze(cont);
|
||||
});
|
||||
return function close() {
|
||||
delete watchContainer.listeners[listenerIndex];
|
||||
delete watchContainer.rawEmitters[listenerIndex];
|
||||
if (!Object.keys(watchContainer.listeners).length) {
|
||||
watchContainer.watcher.stop();
|
||||
delete FSEventsWatchers[watchPath];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Decide whether or not we should start a new higher-level
|
||||
// parent watcher
|
||||
const couldConsolidate = (path) => {
|
||||
let count = 0;
|
||||
for (const watchPath of FSEventsWatchers.keys()) {
|
||||
function couldConsolidate(path) {
|
||||
var keys = Object.keys(FSEventsWatchers);
|
||||
var count = 0;
|
||||
|
||||
for (var i = 0, len = keys.length; i < len; ++i) {
|
||||
var watchPath = keys[i];
|
||||
if (watchPath.indexOf(path) === 0) {
|
||||
count++;
|
||||
if (count >= consolidateThreshhold) {
|
||||
@@ -189,336 +121,292 @@ const couldConsolidate = (path) => {
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
function isConstructor(obj) {
|
||||
return obj.prototype !== undefined && obj.prototype.constructor !== undefined;
|
||||
}
|
||||
|
||||
// returns boolean indicating whether fsevents can be used
|
||||
const canUse = () => fsevents && FSEventsWatchers.size < 128;
|
||||
function canUse() {
|
||||
return fsevents && Object.keys(FSEventsWatchers).length < 128 && isConstructor(fsevents);
|
||||
}
|
||||
|
||||
// determines subdirectory traversal levels from root to path
|
||||
const calcDepth = (path, root) => {
|
||||
let i = 0;
|
||||
function depth(path, root) {
|
||||
var i = 0;
|
||||
while (!path.indexOf(root) && (path = sysPath.dirname(path)) !== root) i++;
|
||||
return i;
|
||||
};
|
||||
|
||||
// returns boolean indicating whether the fsevents' event info has the same type
|
||||
// as the one returned by fs.stat
|
||||
const sameTypes = (info, stats) => (
|
||||
info.type === FSEVENT_TYPE_DIRECTORY && stats.isDirectory() ||
|
||||
info.type === FSEVENT_TYPE_SYMLINK && stats.isSymbolicLink() ||
|
||||
info.type === FSEVENT_TYPE_FILE && stats.isFile()
|
||||
)
|
||||
|
||||
/**
|
||||
* @mixin
|
||||
*/
|
||||
class FsEventsHandler {
|
||||
|
||||
/**
|
||||
* @param {import('../index').FSWatcher} fsw
|
||||
*/
|
||||
constructor(fsw) {
|
||||
this.fsw = fsw;
|
||||
}
|
||||
checkIgnored(path, stats) {
|
||||
const ipaths = this.fsw._ignoredPaths;
|
||||
if (this.fsw._isIgnored(path, stats)) {
|
||||
ipaths.add(path);
|
||||
if (stats && stats.isDirectory()) {
|
||||
ipaths.add(path + ROOT_GLOBSTAR);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ipaths.delete(path);
|
||||
ipaths.delete(path + ROOT_GLOBSTAR);
|
||||
}
|
||||
|
||||
addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts) {
|
||||
const event = watchedDir.has(item) ? EV_CHANGE : EV_ADD;
|
||||
this.handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
}
|
||||
// fake constructor for attaching fsevents-specific prototype methods that
|
||||
// will be copied to FSWatcher's prototype
|
||||
function FsEventsHandler() {}
|
||||
|
||||
async checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts) {
|
||||
try {
|
||||
const stats = await stat(path)
|
||||
if (this.fsw.closed) return;
|
||||
if (sameTypes(info, stats)) {
|
||||
this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
} else {
|
||||
this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code === 'EACCES') {
|
||||
this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
} else {
|
||||
this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Private method: Handle symlinks encountered during directory scan
|
||||
|
||||
handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts) {
|
||||
if (this.fsw.closed || this.checkIgnored(path)) return;
|
||||
// * watchPath - string, file/dir path to be watched with fsevents
|
||||
// * realPath - string, real path (in case of symlinks)
|
||||
// * transform - function, path transformer
|
||||
// * globFilter - function, path filter in case a glob pattern was provided
|
||||
|
||||
if (event === EV_UNLINK) {
|
||||
const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY
|
||||
// suppress unlink events on never before seen files
|
||||
if (isDirectory || watchedDir.has(item)) {
|
||||
this.fsw._remove(parent, item, isDirectory);
|
||||
}
|
||||
} else {
|
||||
if (event === EV_ADD) {
|
||||
// track new directories
|
||||
if (info.type === FSEVENT_TYPE_DIRECTORY) this.fsw._getWatchedDir(path);
|
||||
|
||||
if (info.type === FSEVENT_TYPE_SYMLINK && opts.followSymlinks) {
|
||||
// push symlinks back to the top of the stack to get handled
|
||||
const curDepth = opts.depth === undefined ?
|
||||
undefined : calcDepth(fullPath, realPath) + 1;
|
||||
return this._addToFsEvents(path, false, true, curDepth);
|
||||
}
|
||||
|
||||
// track new paths
|
||||
// (other than symlinks being followed, which will be tracked soon)
|
||||
this.fsw._getWatchedDir(parent).add(item);
|
||||
}
|
||||
/**
|
||||
* @type {'add'|'addDir'|'unlink'|'unlinkDir'}
|
||||
*/
|
||||
const eventName = info.type === FSEVENT_TYPE_DIRECTORY ? event + DIR_SUFFIX : event;
|
||||
this.fsw._emit(eventName, path);
|
||||
if (eventName === EV_ADD_DIR) this._addToFsEvents(path, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle symlinks encountered during directory scan
|
||||
* @param {String} watchPath - file/dir path to be watched with fsevents
|
||||
* @param {String} realPath - real path (in case of symlinks)
|
||||
* @param {Function} transform - path transformer
|
||||
* @param {Function} globFilter - path filter in case a glob pattern was provided
|
||||
* @returns {Function} closer for the watcher instance
|
||||
*/
|
||||
_watchWithFsEvents(watchPath, realPath, transform, globFilter) {
|
||||
if (this.fsw.closed || this.fsw._isIgnored(watchPath)) return;
|
||||
const opts = this.fsw.options;
|
||||
const watchCallback = async (fullPath, flags, info) => {
|
||||
if (this.fsw.closed) return;
|
||||
// Returns close function for the watcher instance
|
||||
FsEventsHandler.prototype._watchWithFsEvents =
|
||||
function(watchPath, realPath, transform, globFilter) {
|
||||
if (this._isIgnored(watchPath)) return;
|
||||
var watchCallback = function(fullPath, flags, info) {
|
||||
if (
|
||||
opts.depth !== undefined &&
|
||||
calcDepth(fullPath, realPath) > opts.depth
|
||||
this.options.depth !== undefined &&
|
||||
depth(fullPath, realPath) > this.options.depth
|
||||
) return;
|
||||
const path = transform(sysPath.join(
|
||||
var path = transform(sysPath.join(
|
||||
watchPath, sysPath.relative(watchPath, fullPath)
|
||||
));
|
||||
if (globFilter && !globFilter(path)) return;
|
||||
// ensure directories are tracked
|
||||
const parent = sysPath.dirname(path);
|
||||
const item = sysPath.basename(path);
|
||||
const watchedDir = this.fsw._getWatchedDir(
|
||||
info.type === FSEVENT_TYPE_DIRECTORY ? path : parent
|
||||
var parent = sysPath.dirname(path);
|
||||
var item = sysPath.basename(path);
|
||||
var watchedDir = this._getWatchedDir(
|
||||
info.type === 'directory' ? path : parent
|
||||
);
|
||||
var checkIgnored = function(stats) {
|
||||
if (this._isIgnored(path, stats)) {
|
||||
this._ignoredPaths[path] = true;
|
||||
if (stats && stats.isDirectory()) {
|
||||
this._ignoredPaths[path + '/**/*'] = true;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
delete this._ignoredPaths[path];
|
||||
delete this._ignoredPaths[path + '/**/*'];
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
// correct for wrong events emitted
|
||||
if (wrongEventFlags.has(flags) || info.event === FSEVENT_UNKNOWN) {
|
||||
if (typeof opts.ignored === FUNCTION_TYPE) {
|
||||
let stats;
|
||||
try {
|
||||
stats = await stat(path);
|
||||
} catch (error) {}
|
||||
if (this.fsw.closed) return;
|
||||
if (this.checkIgnored(path, stats)) return;
|
||||
if (sameTypes(info, stats)) {
|
||||
this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
} else {
|
||||
this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
var handleEvent = function(event) {
|
||||
if (checkIgnored()) return;
|
||||
|
||||
if (event === 'unlink') {
|
||||
// suppress unlink events on never before seen files
|
||||
if (info.type === 'directory' || watchedDir.has(item)) {
|
||||
this._remove(parent, item);
|
||||
}
|
||||
} else {
|
||||
this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
if (event === 'add') {
|
||||
// track new directories
|
||||
if (info.type === 'directory') this._getWatchedDir(path);
|
||||
|
||||
if (info.type === 'symlink' && this.options.followSymlinks) {
|
||||
// push symlinks back to the top of the stack to get handled
|
||||
var curDepth = this.options.depth === undefined ?
|
||||
undefined : depth(fullPath, realPath) + 1;
|
||||
return this._addToFsEvents(path, false, true, curDepth);
|
||||
} else {
|
||||
// track new paths
|
||||
// (other than symlinks being followed, which will be tracked soon)
|
||||
this._getWatchedDir(parent).add(item);
|
||||
}
|
||||
}
|
||||
var eventName = info.type === 'directory' ? event + 'Dir' : event;
|
||||
this._emit(eventName, path);
|
||||
if (eventName === 'addDir') this._addToFsEvents(path, false, true);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
function addOrChange() {
|
||||
handleEvent(watchedDir.has(item) ? 'change' : 'add');
|
||||
}
|
||||
function checkFd() {
|
||||
fs.open(path, 'r', function(error, fd) {
|
||||
if (error) {
|
||||
error.code !== 'EACCES' ?
|
||||
handleEvent('unlink') : addOrChange();
|
||||
} else {
|
||||
fs.close(fd, function(err) {
|
||||
err && err.code !== 'EACCES' ?
|
||||
handleEvent('unlink') : addOrChange();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// correct for wrong events emitted
|
||||
var wrongEventFlags = [
|
||||
69888, 70400, 71424, 72704, 73472, 131328, 131840, 262912
|
||||
];
|
||||
if (wrongEventFlags.indexOf(flags) !== -1 || info.event === 'unknown') {
|
||||
if (typeof this.options.ignored === 'function') {
|
||||
fs.stat(path, function(error, stats) {
|
||||
if (checkIgnored(stats)) return;
|
||||
stats ? addOrChange() : handleEvent('unlink');
|
||||
});
|
||||
} else {
|
||||
checkFd();
|
||||
}
|
||||
} else {
|
||||
switch (info.event) {
|
||||
case FSEVENT_CREATED:
|
||||
case FSEVENT_MODIFIED:
|
||||
return this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
case FSEVENT_DELETED:
|
||||
case FSEVENT_MOVED:
|
||||
return this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts);
|
||||
case 'created':
|
||||
case 'modified':
|
||||
return addOrChange();
|
||||
case 'deleted':
|
||||
case 'moved':
|
||||
return checkFd();
|
||||
}
|
||||
}
|
||||
};
|
||||
}.bind(this);
|
||||
|
||||
const closer = setFSEventsListener(
|
||||
var closer = setFSEventsListener(
|
||||
watchPath,
|
||||
realPath,
|
||||
watchCallback,
|
||||
this.fsw._emitRaw
|
||||
this.emit.bind(this, 'raw')
|
||||
);
|
||||
|
||||
this.fsw._emitReady();
|
||||
this._emitReady();
|
||||
return closer;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle symlinks encountered during directory scan
|
||||
* @param {String} linkPath path to symlink
|
||||
* @param {String} fullPath absolute path to the symlink
|
||||
* @param {Function} transform pre-existing path transformer
|
||||
* @param {Number} curDepth level of subdirectories traversed to where symlink is
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async _handleFsEventsSymlink(linkPath, fullPath, transform, curDepth) {
|
||||
// Private method: Handle symlinks encountered during directory scan
|
||||
|
||||
// * linkPath - string, path to symlink
|
||||
// * fullPath - string, absolute path to the symlink
|
||||
// * transform - function, pre-existing path transformer
|
||||
// * curDepth - int, level of subdirectories traversed to where symlink is
|
||||
|
||||
// Returns nothing
|
||||
FsEventsHandler.prototype._handleFsEventsSymlink =
|
||||
function(linkPath, fullPath, transform, curDepth) {
|
||||
// don't follow the same symlink more than once
|
||||
if (this.fsw.closed || this.fsw._symlinkPaths.has(fullPath)) return;
|
||||
if (this._symlinkPaths[fullPath]) return;
|
||||
else this._symlinkPaths[fullPath] = true;
|
||||
|
||||
this.fsw._symlinkPaths.set(fullPath, true);
|
||||
this.fsw._incrReadyCount();
|
||||
this._readyCount++;
|
||||
|
||||
try {
|
||||
const linkTarget = await realpath(linkPath);
|
||||
if (this.fsw.closed) return;
|
||||
if (this.fsw._isIgnored(linkTarget)) {
|
||||
return this.fsw._emitReady();
|
||||
fs.realpath(linkPath, function(error, linkTarget) {
|
||||
if (this._handleError(error) || this._isIgnored(linkTarget)) {
|
||||
return this._emitReady();
|
||||
}
|
||||
|
||||
this.fsw._incrReadyCount();
|
||||
this._readyCount++;
|
||||
|
||||
// add the linkTarget for watching with a wrapper for transform
|
||||
// that causes emitted paths to incorporate the link's path
|
||||
this._addToFsEvents(linkTarget || linkPath, (path) => {
|
||||
let aliasedPath = linkPath;
|
||||
if (linkTarget && linkTarget !== DOT_SLASH) {
|
||||
this._addToFsEvents(linkTarget || linkPath, function(path) {
|
||||
var dotSlash = '.' + sysPath.sep;
|
||||
var aliasedPath = linkPath;
|
||||
if (linkTarget && linkTarget !== dotSlash) {
|
||||
aliasedPath = path.replace(linkTarget, linkPath);
|
||||
} else if (path !== DOT_SLASH) {
|
||||
} else if (path !== dotSlash) {
|
||||
aliasedPath = sysPath.join(linkPath, path);
|
||||
}
|
||||
return transform(aliasedPath);
|
||||
}, false, curDepth);
|
||||
} catch(error) {
|
||||
if (this.fsw._handleError(error)) {
|
||||
return this.fsw._emitReady();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
// Private method: Handle added path with fsevents
|
||||
|
||||
// * path - string, file/directory path or glob pattern
|
||||
// * transform - function, converts working path to what the user expects
|
||||
// * forceAdd - boolean, ensure add is emitted
|
||||
// * priorDepth - int, level of subdirectories already traversed
|
||||
|
||||
// Returns nothing
|
||||
FsEventsHandler.prototype._addToFsEvents =
|
||||
function(path, transform, forceAdd, priorDepth) {
|
||||
|
||||
// applies transform if provided, otherwise returns same value
|
||||
var processPath = typeof transform === 'function' ?
|
||||
transform : function(val) { return val; };
|
||||
|
||||
var emitAdd = function(newPath, stats) {
|
||||
var pp = processPath(newPath);
|
||||
var isDir = stats.isDirectory();
|
||||
var dirObj = this._getWatchedDir(sysPath.dirname(pp));
|
||||
var base = sysPath.basename(pp);
|
||||
|
||||
// ensure empty dirs get tracked
|
||||
if (isDir) this._getWatchedDir(pp);
|
||||
|
||||
if (dirObj.has(base)) return;
|
||||
dirObj.add(base);
|
||||
|
||||
if (!this.options.ignoreInitial || forceAdd === true) {
|
||||
this._emit(isDir ? 'addDir' : 'add', pp, stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Path} newPath
|
||||
* @param {fs.Stats} stats
|
||||
*/
|
||||
emitAdd(newPath, stats, processPath, opts, forceAdd) {
|
||||
const pp = processPath(newPath);
|
||||
const isDir = stats.isDirectory();
|
||||
const dirObj = this.fsw._getWatchedDir(sysPath.dirname(pp));
|
||||
const base = sysPath.basename(pp);
|
||||
|
||||
// ensure empty dirs get tracked
|
||||
if (isDir) this.fsw._getWatchedDir(pp);
|
||||
if (dirObj.has(base)) return;
|
||||
dirObj.add(base);
|
||||
|
||||
if (!opts.ignoreInitial || forceAdd === true) {
|
||||
this.fsw._emit(isDir ? EV_ADD_DIR : EV_ADD, pp, stats);
|
||||
}
|
||||
}
|
||||
|
||||
initWatch(realPath, path, wh, processPath) {
|
||||
if (this.fsw.closed) return;
|
||||
const closer = this._watchWithFsEvents(
|
||||
wh.watchPath,
|
||||
sysPath.resolve(realPath || wh.watchPath),
|
||||
processPath,
|
||||
wh.globFilter
|
||||
);
|
||||
this.fsw._addPathCloser(path, closer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle added path with fsevents
|
||||
* @param {String} path file/dir path or glob pattern
|
||||
* @param {Function|Boolean=} transform converts working path to what the user expects
|
||||
* @param {Boolean=} forceAdd ensure add is emitted
|
||||
* @param {Number=} priorDepth Level of subdirectories already traversed.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async _addToFsEvents(path, transform, forceAdd, priorDepth) {
|
||||
if (this.fsw.closed) {
|
||||
return;
|
||||
}
|
||||
const opts = this.fsw.options;
|
||||
const processPath = typeof transform === FUNCTION_TYPE ? transform : IDENTITY_FN;
|
||||
|
||||
const wh = this.fsw._getWatchHelpers(path);
|
||||
var wh = this._getWatchHelpers(path);
|
||||
|
||||
// evaluate what is at the path we're being asked to watch
|
||||
try {
|
||||
const stats = await statMethods[wh.statMethod](wh.watchPath);
|
||||
if (this.fsw.closed) return;
|
||||
if (this.fsw._isIgnored(wh.watchPath, stats)) {
|
||||
throw null;
|
||||
fs[wh.statMethod](wh.watchPath, function(error, stats) {
|
||||
if (this._handleError(error) || this._isIgnored(wh.watchPath, stats)) {
|
||||
this._emitReady();
|
||||
return this._emitReady();
|
||||
}
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
// emit addDir unless this is a glob parent
|
||||
if (!wh.globFilter) this.emitAdd(processPath(path), stats, processPath, opts, forceAdd);
|
||||
if (!wh.globFilter) emitAdd(processPath(path), stats);
|
||||
|
||||
// don't recurse further if it would exceed depth setting
|
||||
if (priorDepth && priorDepth > opts.depth) return;
|
||||
if (priorDepth && priorDepth > this.options.depth) return;
|
||||
|
||||
// scan the contents of the dir
|
||||
this.fsw._readdirp(wh.watchPath, {
|
||||
fileFilter: entry => wh.filterPath(entry),
|
||||
directoryFilter: entry => wh.filterDir(entry),
|
||||
...Depth(opts.depth - (priorDepth || 0))
|
||||
}).on(STR_DATA, (entry) => {
|
||||
readdirp({
|
||||
root: wh.watchPath,
|
||||
entryType: 'all',
|
||||
fileFilter: wh.filterPath,
|
||||
directoryFilter: wh.filterDir,
|
||||
lstat: true,
|
||||
depth: this.options.depth - (priorDepth || 0)
|
||||
}).on('data', function(entry) {
|
||||
// need to check filterPath on dirs b/c filterDir is less restrictive
|
||||
if (this.fsw.closed) {
|
||||
return;
|
||||
}
|
||||
if (entry.stats.isDirectory() && !wh.filterPath(entry)) return;
|
||||
if (entry.stat.isDirectory() && !wh.filterPath(entry)) return;
|
||||
|
||||
const joinedPath = sysPath.join(wh.watchPath, entry.path);
|
||||
const {fullPath} = entry;
|
||||
var joinedPath = sysPath.join(wh.watchPath, entry.path);
|
||||
var fullPath = entry.fullPath;
|
||||
|
||||
if (wh.followSymlinks && entry.stats.isSymbolicLink()) {
|
||||
if (wh.followSymlinks && entry.stat.isSymbolicLink()) {
|
||||
// preserve the current depth here since it can't be derived from
|
||||
// real paths past the symlink
|
||||
const curDepth = opts.depth === undefined ?
|
||||
undefined : calcDepth(joinedPath, sysPath.resolve(wh.watchPath)) + 1;
|
||||
var curDepth = this.options.depth === undefined ?
|
||||
undefined : depth(joinedPath, sysPath.resolve(wh.watchPath)) + 1;
|
||||
|
||||
this._handleFsEventsSymlink(joinedPath, fullPath, processPath, curDepth);
|
||||
} else {
|
||||
this.emitAdd(joinedPath, entry.stats, processPath, opts, forceAdd);
|
||||
emitAdd(joinedPath, entry.stat);
|
||||
}
|
||||
}).on(EV_ERROR, EMPTY_FN).on(STR_END, () => {
|
||||
this.fsw._emitReady();
|
||||
});
|
||||
}.bind(this)).on('error', function() {
|
||||
// Ignore readdirp errors
|
||||
}).on('end', this._emitReady);
|
||||
} else {
|
||||
this.emitAdd(wh.watchPath, stats, processPath, opts, forceAdd);
|
||||
this.fsw._emitReady();
|
||||
emitAdd(wh.watchPath, stats);
|
||||
this._emitReady();
|
||||
}
|
||||
} catch (error) {
|
||||
if (!error || this.fsw._handleError(error)) {
|
||||
// TODO: Strange thing: "should not choke on an ignored watch path" will be failed without 2 ready calls -__-
|
||||
this.fsw._emitReady();
|
||||
this.fsw._emitReady();
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
if (opts.persistent && forceAdd !== true) {
|
||||
if (typeof transform === FUNCTION_TYPE) {
|
||||
if (this.options.persistent && forceAdd !== true) {
|
||||
var initWatch = function(error, realPath) {
|
||||
if (this.closed) return;
|
||||
var closer = this._watchWithFsEvents(
|
||||
wh.watchPath,
|
||||
sysPath.resolve(realPath || wh.watchPath),
|
||||
processPath,
|
||||
wh.globFilter
|
||||
);
|
||||
if (closer) {
|
||||
this._closers[path] = this._closers[path] || [];
|
||||
this._closers[path].push(closer);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
if (typeof transform === 'function') {
|
||||
// realpath has already been resolved
|
||||
this.initWatch(undefined, path, wh, processPath);
|
||||
initWatch();
|
||||
} else {
|
||||
let realPath;
|
||||
try {
|
||||
realPath = await realpath(wh.watchPath);
|
||||
} catch (e) {}
|
||||
this.initWatch(realPath, path, wh, processPath);
|
||||
fs.realpath(wh.watchPath, initWatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = FsEventsHandler;
|
||||
module.exports.canUse = canUse;
|
||||
|
||||
838
node_modules/chokidar/lib/nodefs-handler.js
generated
vendored
838
node_modules/chokidar/lib/nodefs-handler.js
generated
vendored
@@ -1,109 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const sysPath = require('path');
|
||||
const { promisify } = require('util');
|
||||
const isBinaryPath = require('is-binary-path');
|
||||
const {
|
||||
isWindows,
|
||||
isLinux,
|
||||
EMPTY_FN,
|
||||
EMPTY_STR,
|
||||
KEY_LISTENERS,
|
||||
KEY_ERR,
|
||||
KEY_RAW,
|
||||
HANDLER_KEYS,
|
||||
EV_CHANGE,
|
||||
EV_ADD,
|
||||
EV_ADD_DIR,
|
||||
EV_ERROR,
|
||||
STR_DATA,
|
||||
STR_END,
|
||||
BRACE_START,
|
||||
STAR
|
||||
} = require('./constants');
|
||||
var fs = require('fs');
|
||||
var sysPath = require('path');
|
||||
var readdirp = require('readdirp');
|
||||
var isBinaryPath = require('is-binary-path');
|
||||
|
||||
const THROTTLE_MODE_WATCH = 'watch';
|
||||
// fs.watch helpers
|
||||
|
||||
const open = promisify(fs.open);
|
||||
const stat = promisify(fs.stat);
|
||||
const lstat = promisify(fs.lstat);
|
||||
const close = promisify(fs.close);
|
||||
const fsrealpath = promisify(fs.realpath);
|
||||
|
||||
const statMethods = { lstat, stat };
|
||||
|
||||
// TODO: emit errors properly. Example: EMFILE on Macos.
|
||||
const foreach = (val, fn) => {
|
||||
if (val instanceof Set) {
|
||||
val.forEach(fn);
|
||||
} else {
|
||||
fn(val);
|
||||
}
|
||||
};
|
||||
|
||||
const addAndConvert = (main, prop, item) => {
|
||||
let container = main[prop];
|
||||
if (!(container instanceof Set)) {
|
||||
main[prop] = container = new Set([container]);
|
||||
}
|
||||
container.add(item);
|
||||
};
|
||||
|
||||
const clearItem = cont => key => {
|
||||
const set = cont[key];
|
||||
if (set instanceof Set) {
|
||||
set.clear();
|
||||
} else {
|
||||
delete cont[key];
|
||||
}
|
||||
};
|
||||
|
||||
const delFromSet = (main, prop, item) => {
|
||||
const container = main[prop];
|
||||
if (container instanceof Set) {
|
||||
container.delete(item);
|
||||
} else if (container === item) {
|
||||
delete main[prop];
|
||||
}
|
||||
};
|
||||
|
||||
const isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
||||
|
||||
/**
|
||||
* @typedef {String} Path
|
||||
*/
|
||||
|
||||
// fs_watch helpers
|
||||
|
||||
// object to hold per-process fs_watch instances
|
||||
// object to hold per-process fs.watch instances
|
||||
// (may be shared across chokidar FSWatcher instances)
|
||||
var FsWatchInstances = Object.create(null);
|
||||
|
||||
/**
|
||||
* @typedef {Object} FsWatchContainer
|
||||
* @property {Set} listeners
|
||||
* @property {Set} errHandlers
|
||||
* @property {Set} rawEmitters
|
||||
* @property {fs.FSWatcher=} watcher
|
||||
* @property {Boolean=} watcherUnusable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {Map<String,FsWatchContainer>}
|
||||
*/
|
||||
const FsWatchInstances = new Map();
|
||||
// Private function: Instantiates the fs.watch interface
|
||||
|
||||
/**
|
||||
* Instantiates the fs_watch interface
|
||||
* @param {String} path to be watched
|
||||
* @param {Object} options to be passed to fs_watch
|
||||
* @param {Function} listener main event handler
|
||||
* @param {Function} errHandler emits info about errors
|
||||
* @param {Function} emitRaw emits raw event data
|
||||
* @returns {fs.FSWatcher} new fsevents instance
|
||||
*/
|
||||
// * path - string, path to be watched
|
||||
// * options - object, options to be passed to fs.watch
|
||||
// * listener - function, main event handler
|
||||
// * errHandler - function, handler which emits info about errors
|
||||
// * emitRaw - function, handler which emits raw event data
|
||||
|
||||
// Returns new fsevents instance
|
||||
function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
|
||||
const handleEvent = (rawEvent, evPath) => {
|
||||
var handleEvent = function(rawEvent, evPath) {
|
||||
listener(path);
|
||||
emitRaw(rawEvent, evPath, {watchedPath: path});
|
||||
|
||||
@@ -111,7 +30,7 @@ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
|
||||
// case the file's watcher misses it (and rely on throttling to de-dupe)
|
||||
if (evPath && path !== evPath) {
|
||||
fsWatchBroadcast(
|
||||
sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath)
|
||||
sysPath.resolve(path, evPath), 'listeners', sysPath.join(path, evPath)
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -122,533 +41,466 @@ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for passing fs_watch event data to a collection of listeners
|
||||
* @param {Path} fullPath absolute path bound to fs_watch instance
|
||||
* @param {String} type listener type
|
||||
* @param {*=} val1 arguments to be passed to listeners
|
||||
* @param {*=} val2
|
||||
* @param {*=} val3
|
||||
*/
|
||||
const fsWatchBroadcast = (fullPath, type, val1, val2, val3) => {
|
||||
const cont = FsWatchInstances.get(fullPath);
|
||||
if (!cont) return;
|
||||
foreach(cont[type], (listener) => {
|
||||
// Private function: Helper for passing fs.watch event data to a
|
||||
// collection of listeners
|
||||
|
||||
// * fullPath - string, absolute path bound to the fs.watch instance
|
||||
// * type - string, listener type
|
||||
// * val[1..3] - arguments to be passed to listeners
|
||||
|
||||
// Returns nothing
|
||||
function fsWatchBroadcast(fullPath, type, val1, val2, val3) {
|
||||
if (!FsWatchInstances[fullPath]) return;
|
||||
FsWatchInstances[fullPath][type].forEach(function(listener) {
|
||||
listener(val1, val2, val3);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates the fs_watch interface or binds listeners
|
||||
* to an existing one covering the same file system entry
|
||||
* @param {String} path
|
||||
* @param {String} fullPath absolute path
|
||||
* @param {Object} options to be passed to fs_watch
|
||||
* @param {Object} handlers container for event listener functions
|
||||
*/
|
||||
const setFsWatchListener = (path, fullPath, options, handlers) => {
|
||||
const {listener, errHandler, rawEmitter} = handlers;
|
||||
let cont = FsWatchInstances.get(fullPath);
|
||||
// Private function: Instantiates the fs.watch interface or binds listeners
|
||||
// to an existing one covering the same file system entry
|
||||
|
||||
/** @type {fs.FSWatcher=} */
|
||||
let watcher;
|
||||
// * path - string, path to be watched
|
||||
// * fullPath - string, absolute path
|
||||
// * options - object, options to be passed to fs.watch
|
||||
// * handlers - object, container for event listener functions
|
||||
|
||||
// Returns close function
|
||||
function setFsWatchListener(path, fullPath, options, handlers) {
|
||||
var listener = handlers.listener;
|
||||
var errHandler = handlers.errHandler;
|
||||
var rawEmitter = handlers.rawEmitter;
|
||||
var container = FsWatchInstances[fullPath];
|
||||
var watcher;
|
||||
if (!options.persistent) {
|
||||
watcher = createFsWatchInstance(
|
||||
path, options, listener, errHandler, rawEmitter
|
||||
);
|
||||
return watcher.close.bind(watcher);
|
||||
}
|
||||
if (cont) {
|
||||
addAndConvert(cont, KEY_LISTENERS, listener);
|
||||
addAndConvert(cont, KEY_ERR, errHandler);
|
||||
addAndConvert(cont, KEY_RAW, rawEmitter);
|
||||
} else {
|
||||
if (!container) {
|
||||
watcher = createFsWatchInstance(
|
||||
path,
|
||||
options,
|
||||
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
||||
fsWatchBroadcast.bind(null, fullPath, 'listeners'),
|
||||
errHandler, // no need to use broadcast here
|
||||
fsWatchBroadcast.bind(null, fullPath, KEY_RAW)
|
||||
fsWatchBroadcast.bind(null, fullPath, 'rawEmitters')
|
||||
);
|
||||
if (!watcher) return;
|
||||
watcher.on(EV_ERROR, async (error) => {
|
||||
const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
|
||||
cont.watcherUnusable = true; // documented since Node 10.4.1
|
||||
var broadcastErr = fsWatchBroadcast.bind(null, fullPath, 'errHandlers');
|
||||
watcher.on('error', function(error) {
|
||||
container.watcherUnusable = true; // documented since Node 10.4.1
|
||||
// Workaround for https://github.com/joyent/node/issues/4337
|
||||
if (isWindows && error.code === 'EPERM') {
|
||||
try {
|
||||
const fd = await open(path, 'r');
|
||||
await close(fd);
|
||||
broadcastErr(error);
|
||||
} catch (err) {}
|
||||
if (process.platform === 'win32' && error.code === 'EPERM') {
|
||||
fs.open(path, 'r', function(err, fd) {
|
||||
if (!err) fs.close(fd, function(err) {
|
||||
if (!err) broadcastErr(error);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
broadcastErr(error);
|
||||
}
|
||||
});
|
||||
cont = {
|
||||
listeners: listener,
|
||||
errHandlers: errHandler,
|
||||
rawEmitters: rawEmitter,
|
||||
watcher
|
||||
container = FsWatchInstances[fullPath] = {
|
||||
listeners: [listener],
|
||||
errHandlers: [errHandler],
|
||||
rawEmitters: [rawEmitter],
|
||||
watcher: watcher
|
||||
};
|
||||
FsWatchInstances.set(fullPath, cont);
|
||||
} else {
|
||||
container.listeners.push(listener);
|
||||
container.errHandlers.push(errHandler);
|
||||
container.rawEmitters.push(rawEmitter);
|
||||
}
|
||||
// const index = cont.listeners.indexOf(listener);
|
||||
var listenerIndex = container.listeners.length - 1;
|
||||
|
||||
// removes this instance's listeners and closes the underlying fs_watch
|
||||
// removes this instance's listeners and closes the underlying fs.watch
|
||||
// instance if there are no more listeners left
|
||||
return () => {
|
||||
delFromSet(cont, KEY_LISTENERS, listener);
|
||||
delFromSet(cont, KEY_ERR, errHandler);
|
||||
delFromSet(cont, KEY_RAW, rawEmitter);
|
||||
if (isEmptySet(cont.listeners)) {
|
||||
// Check to protect against issue gh-730.
|
||||
// if (cont.watcherUnusable) {
|
||||
cont.watcher.close();
|
||||
// }
|
||||
FsWatchInstances.delete(fullPath);
|
||||
HANDLER_KEYS.forEach(clearItem(cont));
|
||||
cont.watcher = undefined;
|
||||
Object.freeze(cont);
|
||||
return function close() {
|
||||
delete container.listeners[listenerIndex];
|
||||
delete container.errHandlers[listenerIndex];
|
||||
delete container.rawEmitters[listenerIndex];
|
||||
if (!Object.keys(container.listeners).length) {
|
||||
if (!container.watcherUnusable) { // check to protect against issue #730
|
||||
container.watcher.close();
|
||||
}
|
||||
delete FsWatchInstances[fullPath];
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// fs_watchFile helpers
|
||||
// fs.watchFile helpers
|
||||
|
||||
// object to hold per-process fs_watchFile instances
|
||||
// object to hold per-process fs.watchFile instances
|
||||
// (may be shared across chokidar FSWatcher instances)
|
||||
const FsWatchFileInstances = new Map();
|
||||
var FsWatchFileInstances = Object.create(null);
|
||||
|
||||
/**
|
||||
* Instantiates the fs_watchFile interface or binds listeners
|
||||
* to an existing one covering the same file system entry
|
||||
* @param {String} path to be watched
|
||||
* @param {String} fullPath absolute path
|
||||
* @param {Object} options options to be passed to fs_watchFile
|
||||
* @param {Object} handlers container for event listener functions
|
||||
* @returns {Function} closer
|
||||
*/
|
||||
const setFsWatchFileListener = (path, fullPath, options, handlers) => {
|
||||
const {listener, rawEmitter} = handlers;
|
||||
let cont = FsWatchFileInstances.get(fullPath);
|
||||
// Private function: Instantiates the fs.watchFile interface or binds listeners
|
||||
// to an existing one covering the same file system entry
|
||||
|
||||
/* eslint-disable no-unused-vars, prefer-destructuring */
|
||||
let listeners = new Set();
|
||||
let rawEmitters = new Set();
|
||||
// * path - string, path to be watched
|
||||
// * fullPath - string, absolute path
|
||||
// * options - object, options to be passed to fs.watchFile
|
||||
// * handlers - object, container for event listener functions
|
||||
|
||||
const copts = cont && cont.options;
|
||||
if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
|
||||
// Returns close function
|
||||
function setFsWatchFileListener(path, fullPath, options, handlers) {
|
||||
var listener = handlers.listener;
|
||||
var rawEmitter = handlers.rawEmitter;
|
||||
var container = FsWatchFileInstances[fullPath];
|
||||
var listeners = [];
|
||||
var rawEmitters = [];
|
||||
if (
|
||||
container && (
|
||||
container.options.persistent < options.persistent ||
|
||||
container.options.interval > options.interval
|
||||
)
|
||||
) {
|
||||
// "Upgrade" the watcher to persistence or a quicker interval.
|
||||
// This creates some unlikely edge case issues if the user mixes
|
||||
// settings in a very weird way, but solving for those cases
|
||||
// doesn't seem worthwhile for the added complexity.
|
||||
listeners = cont.listeners;
|
||||
rawEmitters = cont.rawEmitters;
|
||||
listeners = container.listeners;
|
||||
rawEmitters = container.rawEmitters;
|
||||
fs.unwatchFile(fullPath);
|
||||
cont = undefined;
|
||||
container = false;
|
||||
}
|
||||
|
||||
/* eslint-enable no-unused-vars, prefer-destructuring */
|
||||
|
||||
if (cont) {
|
||||
addAndConvert(cont, KEY_LISTENERS, listener);
|
||||
addAndConvert(cont, KEY_RAW, rawEmitter);
|
||||
} else {
|
||||
// TODO
|
||||
// listeners.add(listener);
|
||||
// rawEmitters.add(rawEmitter);
|
||||
cont = {
|
||||
listeners: listener,
|
||||
rawEmitters: rawEmitter,
|
||||
options,
|
||||
watcher: fs.watchFile(fullPath, options, (curr, prev) => {
|
||||
foreach(cont.rawEmitters, (rawEmitter) => {
|
||||
rawEmitter(EV_CHANGE, fullPath, {curr, prev});
|
||||
if (!container) {
|
||||
listeners.push(listener);
|
||||
rawEmitters.push(rawEmitter);
|
||||
container = FsWatchFileInstances[fullPath] = {
|
||||
listeners: listeners,
|
||||
rawEmitters: rawEmitters,
|
||||
options: options,
|
||||
watcher: fs.watchFile(fullPath, options, function(curr, prev) {
|
||||
container.rawEmitters.forEach(function(rawEmitter) {
|
||||
rawEmitter('change', fullPath, {curr: curr, prev: prev});
|
||||
});
|
||||
const currmtime = curr.mtimeMs;
|
||||
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
||||
foreach(cont.listeners, (listener) => listener(path, curr));
|
||||
var currmtime = curr.mtime.getTime();
|
||||
if (curr.size !== prev.size || currmtime > prev.mtime.getTime() || currmtime === 0) {
|
||||
container.listeners.forEach(function(listener) {
|
||||
listener(path, curr);
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
FsWatchFileInstances.set(fullPath, cont);
|
||||
} else {
|
||||
container.listeners.push(listener);
|
||||
container.rawEmitters.push(rawEmitter);
|
||||
}
|
||||
// const index = cont.listeners.indexOf(listener);
|
||||
var listenerIndex = container.listeners.length - 1;
|
||||
|
||||
// Removes this instance's listeners and closes the underlying fs_watchFile
|
||||
// instance if there are no more listeners left.
|
||||
return () => {
|
||||
delFromSet(cont, KEY_LISTENERS, listener);
|
||||
delFromSet(cont, KEY_RAW, rawEmitter);
|
||||
if (isEmptySet(cont.listeners)) {
|
||||
FsWatchFileInstances.delete(fullPath);
|
||||
// removes this instance's listeners and closes the underlying fs.watchFile
|
||||
// instance if there are no more listeners left
|
||||
return function close() {
|
||||
delete container.listeners[listenerIndex];
|
||||
delete container.rawEmitters[listenerIndex];
|
||||
if (!Object.keys(container.listeners).length) {
|
||||
fs.unwatchFile(fullPath);
|
||||
cont.options = cont.watcher = undefined;
|
||||
Object.freeze(cont);
|
||||
delete FsWatchFileInstances[fullPath];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @mixin
|
||||
*/
|
||||
class NodeFsHandler {
|
||||
|
||||
/**
|
||||
* @param {import("../index").FSWatcher} fsW
|
||||
*/
|
||||
constructor(fsW) {
|
||||
this.fsw = fsW;
|
||||
this._boundHandleError = (error) => fsW._handleError(error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch file for changes with fs_watchFile or fs_watch.
|
||||
* @param {String} path to file or dir
|
||||
* @param {Function} listener on fs change
|
||||
* @returns {Function} closer for the watcher instance
|
||||
*/
|
||||
_watchWithNodeFs(path, listener) {
|
||||
const opts = this.fsw.options;
|
||||
const directory = sysPath.dirname(path);
|
||||
const basename = sysPath.basename(path);
|
||||
const parent = this.fsw._getWatchedDir(directory);
|
||||
parent.add(basename);
|
||||
const absolutePath = sysPath.resolve(path);
|
||||
const options = {persistent: opts.persistent};
|
||||
if (!listener) listener = EMPTY_FN;
|
||||
// fake constructor for attaching nodefs-specific prototype methods that
|
||||
// will be copied to FSWatcher's prototype
|
||||
function NodeFsHandler() {}
|
||||
|
||||
let closer;
|
||||
if (opts.usePolling) {
|
||||
options.interval = opts.enableBinaryInterval && isBinaryPath(basename) ?
|
||||
opts.binaryInterval : opts.interval;
|
||||
// Private method: Watch file for changes with fs.watchFile or fs.watch.
|
||||
|
||||
// * path - string, path to file or directory.
|
||||
// * listener - function, to be executed on fs change.
|
||||
|
||||
// Returns close function for the watcher instance
|
||||
NodeFsHandler.prototype._watchWithNodeFs =
|
||||
function(path, listener) {
|
||||
var directory = sysPath.dirname(path);
|
||||
var basename = sysPath.basename(path);
|
||||
var parent = this._getWatchedDir(directory);
|
||||
parent.add(basename);
|
||||
var absolutePath = sysPath.resolve(path);
|
||||
var options = {persistent: this.options.persistent};
|
||||
if (!listener) listener = Function.prototype; // empty function
|
||||
|
||||
var closer;
|
||||
if (this.options.usePolling) {
|
||||
options.interval = this.enableBinaryInterval && isBinaryPath(basename) ?
|
||||
this.options.binaryInterval : this.options.interval;
|
||||
closer = setFsWatchFileListener(path, absolutePath, options, {
|
||||
listener,
|
||||
rawEmitter: this.fsw._emitRaw
|
||||
listener: listener,
|
||||
rawEmitter: this.emit.bind(this, 'raw')
|
||||
});
|
||||
} else {
|
||||
closer = setFsWatchListener(path, absolutePath, options, {
|
||||
listener,
|
||||
errHandler: this._boundHandleError,
|
||||
rawEmitter: this.fsw._emitRaw
|
||||
listener: listener,
|
||||
errHandler: this._handleError.bind(this),
|
||||
rawEmitter: this.emit.bind(this, 'raw')
|
||||
});
|
||||
}
|
||||
return closer;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Watch a file and emit add event if warranted.
|
||||
* @param {Path} file Path
|
||||
* @param {fs.Stats} stats result of fs_stat
|
||||
* @param {Boolean} initialAdd was the file added at watch instantiation?
|
||||
* @returns {Function} closer for the watcher instance
|
||||
*/
|
||||
_handleFile(file, stats, initialAdd) {
|
||||
if (this.fsw.closed) {
|
||||
return;
|
||||
}
|
||||
const dirname = sysPath.dirname(file);
|
||||
const basename = sysPath.basename(file);
|
||||
const parent = this.fsw._getWatchedDir(dirname);
|
||||
// Private method: Watch a file and emit add event if warranted
|
||||
|
||||
// * file - string, the file's path
|
||||
// * stats - object, result of fs.stat
|
||||
// * initialAdd - boolean, was the file added at watch instantiation?
|
||||
// * callback - function, called when done processing as a newly seen file
|
||||
|
||||
// Returns close function for the watcher instance
|
||||
NodeFsHandler.prototype._handleFile =
|
||||
function(file, stats, initialAdd, callback) {
|
||||
var dirname = sysPath.dirname(file);
|
||||
var basename = sysPath.basename(file);
|
||||
var parent = this._getWatchedDir(dirname);
|
||||
// stats is always present
|
||||
let prevStats = stats;
|
||||
var prevStats = stats;
|
||||
|
||||
// if the file is already being watched, do nothing
|
||||
if (parent.has(basename)) return;
|
||||
if (parent.has(basename)) return callback();
|
||||
|
||||
const listener = async (path, newStats) => {
|
||||
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5)) return;
|
||||
if (!newStats || newStats.mtimeMs === 0) {
|
||||
try {
|
||||
const newStats = await stat(file);
|
||||
if (this.fsw.closed) return;
|
||||
// Check that change event was not fired because of changed only accessTime.
|
||||
const at = newStats.atimeMs;
|
||||
const mt = newStats.mtimeMs;
|
||||
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
||||
this.fsw._emit(EV_CHANGE, file, newStats);
|
||||
}
|
||||
if (isLinux && prevStats.ino !== newStats.ino) {
|
||||
this.fsw._closeFile(path)
|
||||
prevStats = newStats;
|
||||
this.fsw._addPathCloser(path, this._watchWithNodeFs(file, listener));
|
||||
} else {
|
||||
prevStats = newStats;
|
||||
}
|
||||
} catch (error) {
|
||||
// kick off the watcher
|
||||
var closer = this._watchWithNodeFs(file, function(path, newStats) {
|
||||
if (!this._throttle('watch', file, 5)) return;
|
||||
if (!newStats || newStats && newStats.mtime.getTime() === 0) {
|
||||
fs.stat(file, function(error, newStats) {
|
||||
// Fix issues where mtime is null but file is still present
|
||||
this.fsw._remove(dirname, basename);
|
||||
}
|
||||
// add is about to be emitted if file not already tracked in parent
|
||||
if (error) {
|
||||
this._remove(dirname, basename);
|
||||
} else {
|
||||
// Check that change event was not fired because of changed only accessTime.
|
||||
var at = newStats.atime.getTime();
|
||||
var mt = newStats.mtime.getTime();
|
||||
if (!at || at <= mt || mt !== prevStats.mtime.getTime()) {
|
||||
this._emit('change', file, newStats);
|
||||
}
|
||||
prevStats = newStats;
|
||||
}
|
||||
}.bind(this));
|
||||
// add is about to be emitted if file not already tracked in parent
|
||||
} else if (parent.has(basename)) {
|
||||
// Check that change event was not fired because of changed only accessTime.
|
||||
const at = newStats.atimeMs;
|
||||
const mt = newStats.mtimeMs;
|
||||
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
||||
this.fsw._emit(EV_CHANGE, file, newStats);
|
||||
var at = newStats.atime.getTime();
|
||||
var mt = newStats.mtime.getTime();
|
||||
if (!at || at <= mt || mt !== prevStats.mtime.getTime()) {
|
||||
this._emit('change', file, newStats);
|
||||
}
|
||||
prevStats = newStats;
|
||||
}
|
||||
}
|
||||
// kick off the watcher
|
||||
const closer = this._watchWithNodeFs(file, listener);
|
||||
}.bind(this));
|
||||
|
||||
// emit an add event if we're supposed to
|
||||
if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {
|
||||
if (!this.fsw._throttle(EV_ADD, file, 0)) return;
|
||||
this.fsw._emit(EV_ADD, file, stats);
|
||||
if (!(initialAdd && this.options.ignoreInitial)) {
|
||||
if (!this._throttle('add', file, 0)) return;
|
||||
this._emit('add', file, stats);
|
||||
}
|
||||
|
||||
if (callback) callback();
|
||||
return closer;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle symlinks encountered while reading a dir.
|
||||
* @param {Object} entry returned by readdirp
|
||||
* @param {String} directory path of dir being read
|
||||
* @param {String} path of this item
|
||||
* @param {String} item basename of this item
|
||||
* @returns {Promise<Boolean>} true if no more processing is needed for this entry.
|
||||
*/
|
||||
async _handleSymlink(entry, directory, path, item) {
|
||||
if (this.fsw.closed) {
|
||||
return;
|
||||
}
|
||||
const full = entry.fullPath;
|
||||
const dir = this.fsw._getWatchedDir(directory);
|
||||
// Private method: Handle symlinks encountered while reading a dir
|
||||
|
||||
if (!this.fsw.options.followSymlinks) {
|
||||
// * entry - object, entry object returned by readdirp
|
||||
// * directory - string, path of the directory being read
|
||||
// * path - string, path of this item
|
||||
// * item - string, basename of this item
|
||||
|
||||
// Returns true if no more processing is needed for this entry.
|
||||
NodeFsHandler.prototype._handleSymlink =
|
||||
function(entry, directory, path, item) {
|
||||
var full = entry.fullPath;
|
||||
var dir = this._getWatchedDir(directory);
|
||||
|
||||
if (!this.options.followSymlinks) {
|
||||
// watch symlink directly (don't follow) and detect changes
|
||||
this.fsw._incrReadyCount();
|
||||
|
||||
let linkPath;
|
||||
try {
|
||||
linkPath = await fsrealpath(path);
|
||||
} catch (e) {
|
||||
this.fsw._emitReady();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.fsw.closed) return;
|
||||
if (dir.has(item)) {
|
||||
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
||||
this.fsw._symlinkPaths.set(full, linkPath);
|
||||
this.fsw._emit(EV_CHANGE, path, entry.stats);
|
||||
this._readyCount++;
|
||||
fs.realpath(path, function(error, linkPath) {
|
||||
if (dir.has(item)) {
|
||||
if (this._symlinkPaths[full] !== linkPath) {
|
||||
this._symlinkPaths[full] = linkPath;
|
||||
this._emit('change', path, entry.stat);
|
||||
}
|
||||
} else {
|
||||
dir.add(item);
|
||||
this._symlinkPaths[full] = linkPath;
|
||||
this._emit('add', path, entry.stat);
|
||||
}
|
||||
} else {
|
||||
dir.add(item);
|
||||
this.fsw._symlinkPaths.set(full, linkPath);
|
||||
this.fsw._emit(EV_ADD, path, entry.stats);
|
||||
}
|
||||
this.fsw._emitReady();
|
||||
this._emitReady();
|
||||
}.bind(this));
|
||||
return true;
|
||||
}
|
||||
|
||||
// don't follow the same symlink more than once
|
||||
if (this.fsw._symlinkPaths.has(full)) {
|
||||
return true;
|
||||
if (this._symlinkPaths[full]) return true;
|
||||
else this._symlinkPaths[full] = true;
|
||||
};
|
||||
|
||||
// Private method: Read directory to add / remove files from `@watched` list
|
||||
// and re-read it on change.
|
||||
|
||||
// * dir - string, fs path.
|
||||
// * stats - object, result of fs.stat
|
||||
// * initialAdd - boolean, was the file added at watch instantiation?
|
||||
// * depth - int, depth relative to user-supplied path
|
||||
// * target - string, child path actually targeted for watch
|
||||
// * wh - object, common watch helpers for this path
|
||||
// * callback - function, called when dir scan is complete
|
||||
|
||||
// Returns close function for the watcher instance
|
||||
NodeFsHandler.prototype._handleDir =
|
||||
function(dir, stats, initialAdd, depth, target, wh, callback) {
|
||||
var parentDir = this._getWatchedDir(sysPath.dirname(dir));
|
||||
var tracked = parentDir.has(sysPath.basename(dir));
|
||||
if (!(initialAdd && this.options.ignoreInitial) && !target && !tracked) {
|
||||
if (!wh.hasGlob || wh.globFilter(dir)) this._emit('addDir', dir, stats);
|
||||
}
|
||||
|
||||
this.fsw._symlinkPaths.set(full, true);
|
||||
}
|
||||
// ensure dir is tracked (harmless if redundant)
|
||||
parentDir.add(sysPath.basename(dir));
|
||||
this._getWatchedDir(dir);
|
||||
|
||||
_handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
|
||||
// Normalize the directory name on Windows
|
||||
directory = sysPath.join(directory, EMPTY_STR);
|
||||
var read = function(directory, initialAdd, done) {
|
||||
// Normalize the directory name on Windows
|
||||
directory = sysPath.join(directory, '');
|
||||
|
||||
if (!wh.hasGlob) {
|
||||
throttler = this.fsw._throttle('readdir', directory, 1000);
|
||||
if (!throttler) return;
|
||||
}
|
||||
|
||||
const previous = this.fsw._getWatchedDir(wh.path);
|
||||
const current = new Set();
|
||||
|
||||
let stream = this.fsw._readdirp(directory, {
|
||||
fileFilter: entry => wh.filterPath(entry),
|
||||
directoryFilter: entry => wh.filterDir(entry),
|
||||
depth: 0
|
||||
}).on(STR_DATA, async (entry) => {
|
||||
if (this.fsw.closed) {
|
||||
stream = undefined;
|
||||
return;
|
||||
}
|
||||
const item = entry.path;
|
||||
let path = sysPath.join(directory, item);
|
||||
current.add(item);
|
||||
|
||||
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) {
|
||||
return;
|
||||
if (!wh.hasGlob) {
|
||||
var throttler = this._throttle('readdir', directory, 1000);
|
||||
if (!throttler) return;
|
||||
}
|
||||
|
||||
if (this.fsw.closed) {
|
||||
stream = undefined;
|
||||
return;
|
||||
}
|
||||
// Files that present in current directory snapshot
|
||||
// but absent in previous are added to watch list and
|
||||
// emit `add` event.
|
||||
if (item === target || !target && !previous.has(item)) {
|
||||
this.fsw._incrReadyCount();
|
||||
var previous = this._getWatchedDir(wh.path);
|
||||
var current = [];
|
||||
|
||||
// ensure relativeness of path is preserved in case of watcher reuse
|
||||
path = sysPath.join(dir, sysPath.relative(dir, path));
|
||||
readdirp({
|
||||
root: directory,
|
||||
entryType: 'all',
|
||||
fileFilter: wh.filterPath,
|
||||
directoryFilter: wh.filterDir,
|
||||
depth: 0,
|
||||
lstat: true
|
||||
}).on('data', function(entry) {
|
||||
var item = entry.path;
|
||||
var path = sysPath.join(directory, item);
|
||||
current.push(item);
|
||||
|
||||
this._addToNodeFs(path, initialAdd, wh, depth + 1);
|
||||
}
|
||||
}).on(EV_ERROR, this._boundHandleError);
|
||||
if (entry.stat.isSymbolicLink() &&
|
||||
this._handleSymlink(entry, directory, path, item)) return;
|
||||
|
||||
return new Promise(resolve =>
|
||||
stream.once(STR_END, () => {
|
||||
if (this.fsw.closed) {
|
||||
stream = undefined;
|
||||
return;
|
||||
// Files that present in current directory snapshot
|
||||
// but absent in previous are added to watch list and
|
||||
// emit `add` event.
|
||||
if (item === target || !target && !previous.has(item)) {
|
||||
this._readyCount++;
|
||||
|
||||
// ensure relativeness of path is preserved in case of watcher reuse
|
||||
path = sysPath.join(dir, sysPath.relative(dir, path));
|
||||
|
||||
this._addToNodeFs(path, initialAdd, wh, depth + 1);
|
||||
}
|
||||
const wasThrottled = throttler ? throttler.clear() : false;
|
||||
|
||||
resolve();
|
||||
}.bind(this)).on('end', function() {
|
||||
var wasThrottled = throttler ? throttler.clear() : false;
|
||||
if (done) done();
|
||||
|
||||
// Files that absent in current directory snapshot
|
||||
// but present in previous emit `remove` event
|
||||
// and are removed from @watched[directory].
|
||||
previous.getChildren().filter((item) => {
|
||||
previous.children().filter(function(item) {
|
||||
return item !== directory &&
|
||||
!current.has(item) &&
|
||||
current.indexOf(item) === -1 &&
|
||||
// in case of intersecting globs;
|
||||
// a path may have been filtered out of this readdir, but
|
||||
// shouldn't be removed because it matches a different glob
|
||||
(!wh.hasGlob || wh.filterPath({
|
||||
fullPath: sysPath.resolve(directory, item)
|
||||
}));
|
||||
}).forEach((item) => {
|
||||
this.fsw._remove(directory, item);
|
||||
});
|
||||
|
||||
stream = undefined;
|
||||
}).forEach(function(item) {
|
||||
this._remove(directory, item);
|
||||
}, this);
|
||||
|
||||
// one more time for any missed in case changes came in extremely quickly
|
||||
if (wasThrottled) this._handleRead(directory, false, wh, target, dir, depth, throttler);
|
||||
})
|
||||
);
|
||||
}
|
||||
if (wasThrottled) read(directory, false);
|
||||
}.bind(this)).on('error', this._handleError.bind(this));
|
||||
}.bind(this);
|
||||
|
||||
/**
|
||||
* Read directory to add / remove files from `@watched` list and re-read it on change.
|
||||
* @param {String} dir fs path
|
||||
* @param {fs.Stats} stats
|
||||
* @param {Boolean} initialAdd
|
||||
* @param {Number} depth relative to user-supplied path
|
||||
* @param {String} target child path targeted for watch
|
||||
* @param {Object} wh Common watch helpers for this path
|
||||
* @param {String} realpath
|
||||
* @returns {Promise<Function>} closer for the watcher instance.
|
||||
*/
|
||||
async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {
|
||||
const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
|
||||
const tracked = parentDir.has(sysPath.basename(dir));
|
||||
if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
|
||||
if (!wh.hasGlob || wh.globFilter(dir)) this.fsw._emit(EV_ADD_DIR, dir, stats);
|
||||
}
|
||||
var closer;
|
||||
|
||||
// ensure dir is tracked (harmless if redundant)
|
||||
parentDir.add(sysPath.basename(dir));
|
||||
this.fsw._getWatchedDir(dir);
|
||||
let throttler;
|
||||
let closer;
|
||||
|
||||
const oDepth = this.fsw.options.depth;
|
||||
if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {
|
||||
if (!target) {
|
||||
await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
|
||||
if (this.fsw.closed) return;
|
||||
}
|
||||
|
||||
closer = this._watchWithNodeFs(dir, (dirPath, stats) => {
|
||||
if (this.options.depth == null || depth <= this.options.depth) {
|
||||
if (!target) read(dir, initialAdd, callback);
|
||||
closer = this._watchWithNodeFs(dir, function(dirPath, stats) {
|
||||
// if current directory is removed, do nothing
|
||||
if (stats && stats.mtimeMs === 0) return;
|
||||
if (stats && stats.mtime.getTime() === 0) return;
|
||||
|
||||
this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
|
||||
read(dirPath, false);
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
return closer;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle added file, directory, or glob pattern.
|
||||
* Delegates call to _handleFile / _handleDir after checks.
|
||||
* @param {String} path to file or ir
|
||||
* @param {Boolean} initialAdd was the file added at watch instantiation?
|
||||
* @param {Object} priorWh depth relative to user-supplied path
|
||||
* @param {Number} depth Child path actually targeted for watch
|
||||
* @param {String=} target Child path actually targeted for watch
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async _addToNodeFs(path, initialAdd, priorWh, depth, target) {
|
||||
const ready = this.fsw._emitReady;
|
||||
if (this.fsw._isIgnored(path) || this.fsw.closed) {
|
||||
// Private method: Handle added file, directory, or glob pattern.
|
||||
// Delegates call to _handleFile / _handleDir after checks.
|
||||
|
||||
// * path - string, path to file or directory.
|
||||
// * initialAdd - boolean, was the file added at watch instantiation?
|
||||
// * depth - int, depth relative to user-supplied path
|
||||
// * target - string, child path actually targeted for watch
|
||||
// * callback - function, indicates whether the path was found or not
|
||||
|
||||
// Returns nothing
|
||||
NodeFsHandler.prototype._addToNodeFs =
|
||||
function(path, initialAdd, priorWh, depth, target, callback) {
|
||||
if (!callback) callback = Function.prototype;
|
||||
var ready = this._emitReady;
|
||||
if (this._isIgnored(path) || this.closed) {
|
||||
ready();
|
||||
return false;
|
||||
return callback(null, false);
|
||||
}
|
||||
|
||||
const wh = this.fsw._getWatchHelpers(path, depth);
|
||||
var wh = this._getWatchHelpers(path, depth);
|
||||
if (!wh.hasGlob && priorWh) {
|
||||
wh.hasGlob = priorWh.hasGlob;
|
||||
wh.globFilter = priorWh.globFilter;
|
||||
wh.filterPath = entry => priorWh.filterPath(entry);
|
||||
wh.filterDir = entry => priorWh.filterDir(entry);
|
||||
wh.filterPath = priorWh.filterPath;
|
||||
wh.filterDir = priorWh.filterDir;
|
||||
}
|
||||
|
||||
// evaluate what is at the path we're being asked to watch
|
||||
try {
|
||||
const stats = await statMethods[wh.statMethod](wh.watchPath);
|
||||
if (this.fsw.closed) return;
|
||||
if (this.fsw._isIgnored(wh.watchPath, stats)) {
|
||||
fs[wh.statMethod](wh.watchPath, function(error, stats) {
|
||||
if (this._handleError(error)) return callback(null, path);
|
||||
if (this._isIgnored(wh.watchPath, stats)) {
|
||||
ready();
|
||||
return false;
|
||||
return callback(null, false);
|
||||
}
|
||||
|
||||
const follow = this.fsw.options.followSymlinks && !path.includes(STAR) && !path.includes(BRACE_START);
|
||||
let closer;
|
||||
var initDir = function(dir, target) {
|
||||
return this._handleDir(dir, stats, initialAdd, depth, target, wh, ready);
|
||||
}.bind(this);
|
||||
|
||||
var closer;
|
||||
if (stats.isDirectory()) {
|
||||
const absPath = sysPath.resolve(path);
|
||||
const targetPath = follow ? await fsrealpath(path) : path;
|
||||
if (this.fsw.closed) return;
|
||||
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
||||
if (this.fsw.closed) return;
|
||||
// preserve this symlink's target path
|
||||
if (absPath !== targetPath && targetPath !== undefined) {
|
||||
this.fsw._symlinkPaths.set(absPath, targetPath);
|
||||
}
|
||||
closer = initDir(wh.watchPath, target);
|
||||
} else if (stats.isSymbolicLink()) {
|
||||
const targetPath = follow ? await fsrealpath(path) : path;
|
||||
if (this.fsw.closed) return;
|
||||
const parent = sysPath.dirname(wh.watchPath);
|
||||
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
||||
this.fsw._emit(EV_ADD, wh.watchPath, stats);
|
||||
closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
|
||||
if (this.fsw.closed) return;
|
||||
var parent = sysPath.dirname(wh.watchPath);
|
||||
this._getWatchedDir(parent).add(wh.watchPath);
|
||||
this._emit('add', wh.watchPath, stats);
|
||||
closer = initDir(parent, path);
|
||||
|
||||
// preserve this symlink's target path
|
||||
if (targetPath !== undefined) {
|
||||
this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
|
||||
}
|
||||
fs.realpath(path, function(error, targetPath) {
|
||||
this._symlinkPaths[sysPath.resolve(path)] = targetPath;
|
||||
ready();
|
||||
}.bind(this));
|
||||
} else {
|
||||
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
||||
closer = this._handleFile(wh.watchPath, stats, initialAdd, ready);
|
||||
}
|
||||
ready();
|
||||
|
||||
this.fsw._addPathCloser(path, closer);
|
||||
return false;
|
||||
|
||||
} catch (error) {
|
||||
if (this.fsw._handleError(error)) {
|
||||
ready();
|
||||
return path;
|
||||
if (closer) {
|
||||
this._closers[path] = this._closers[path] || [];
|
||||
this._closers[path].push(closer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
callback(null, false);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
module.exports = NodeFsHandler;
|
||||
|
||||
120
node_modules/chokidar/package.json
generated
vendored
120
node_modules/chokidar/package.json
generated
vendored
@@ -1,61 +1,7 @@
|
||||
{
|
||||
"name": "chokidar",
|
||||
"description": "Minimal and efficient cross-platform file watching library",
|
||||
"version": "3.5.3",
|
||||
"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",
|
||||
"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",
|
||||
"nyc": "^15.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 .",
|
||||
"mocha": "mocha --exit --timeout 90000",
|
||||
"test": "npm run lint && npm run mocha"
|
||||
},
|
||||
"description": "A neat wrapper around node.js fs.watch / fs.watchFile / fsevents.",
|
||||
"version": "2.1.8",
|
||||
"keywords": [
|
||||
"fs",
|
||||
"watch",
|
||||
@@ -66,20 +12,52 @@
|
||||
"fsevents"
|
||||
],
|
||||
"types": "./types/index.d.ts",
|
||||
"nyc": {
|
||||
"include": [
|
||||
"index.js",
|
||||
"lib/*.js"
|
||||
],
|
||||
"reporter": [
|
||||
"html",
|
||||
"text"
|
||||
]
|
||||
"homepage": "https://github.com/paulmillr/chokidar",
|
||||
"author": "Paul Miller (https://paulmillr.com), Elan Shanker",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paulmillr/chokidar.git"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
]
|
||||
"bugs": {
|
||||
"url": "https://github.com/paulmillr/chokidar/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "nyc mocha --exit",
|
||||
"coveralls": "nyc report --reporter=text-lcov | coveralls",
|
||||
"dtslint": "dtslint types"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"lib/",
|
||||
"types/index.d.ts"
|
||||
],
|
||||
"dependencies": {
|
||||
"anymatch": "^2.0.0",
|
||||
"async-each": "^1.0.1",
|
||||
"braces": "^2.3.2",
|
||||
"glob-parent": "^3.1.0",
|
||||
"inherits": "^2.0.3",
|
||||
"is-binary-path": "^1.0.0",
|
||||
"is-glob": "^4.0.0",
|
||||
"normalize-path": "^3.0.0",
|
||||
"path-is-absolute": "^1.0.0",
|
||||
"readdirp": "^2.2.1",
|
||||
"upath": "^1.1.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "^1.2.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^11.9.4",
|
||||
"chai": "^3.2.0",
|
||||
"coveralls": "^3.0.1",
|
||||
"dtslint": "0.4.1",
|
||||
"graceful-fs": "4.1.4",
|
||||
"mocha": "^5.2.0",
|
||||
"nyc": "^11.8.0",
|
||||
"rimraf": "^2.4.3",
|
||||
"sinon": "^1.10.3",
|
||||
"sinon-chai": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
33
node_modules/chokidar/types/index.d.ts
generated
vendored
33
node_modules/chokidar/types/index.d.ts
generated
vendored
@@ -4,11 +4,16 @@
|
||||
|
||||
import * as fs from "fs";
|
||||
import { EventEmitter } from "events";
|
||||
import { Matcher } from 'anymatch';
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
export interface WatchedPaths {
|
||||
[directory: string]: string[];
|
||||
}
|
||||
|
||||
export class FSWatcher extends EventEmitter implements fs.FSWatcher {
|
||||
options: WatchOptions;
|
||||
|
||||
/**
|
||||
* Constructs a new FSWatcher instance with optional WatchOptions parameter.
|
||||
*/
|
||||
@@ -18,13 +23,13 @@ export class FSWatcher extends EventEmitter implements fs.FSWatcher {
|
||||
* Add files, directories, or glob patterns for tracking. Takes an array of strings or just one
|
||||
* string.
|
||||
*/
|
||||
add(paths: string | ReadonlyArray<string>): this;
|
||||
add(paths: string | string[]): void;
|
||||
|
||||
/**
|
||||
* Stop watching files, directories, or glob patterns. Takes an array of strings or just one
|
||||
* string.
|
||||
*/
|
||||
unwatch(paths: string | ReadonlyArray<string>): this;
|
||||
unwatch(paths: string | string[]): void;
|
||||
|
||||
/**
|
||||
* Returns an object representing all the paths on the file system being watched by this
|
||||
@@ -32,21 +37,19 @@ export class FSWatcher extends EventEmitter implements fs.FSWatcher {
|
||||
* the `cwd` option was used), and the values are arrays of the names of the items contained in
|
||||
* each directory.
|
||||
*/
|
||||
getWatched(): {
|
||||
[directory: string]: string[];
|
||||
};
|
||||
getWatched(): WatchedPaths;
|
||||
|
||||
/**
|
||||
* Removes all listeners from watched files.
|
||||
*/
|
||||
close(): Promise<void>;
|
||||
close(): 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
|
||||
* Error occured
|
||||
*/
|
||||
on(event: 'error', listener: (error: Error) => void): this;
|
||||
|
||||
@@ -74,13 +77,13 @@ export interface WatchOptions {
|
||||
persistent?: boolean;
|
||||
|
||||
/**
|
||||
* ([anymatch](https://github.com/micromatch/anymatch)-compatible definition) Defines files/paths to
|
||||
* ([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).
|
||||
* [`fs.Stats`](http://nodejs.org/api/fs.html#fs_class_fs_stats) object of that path).
|
||||
*/
|
||||
ignored?: Matcher;
|
||||
ignored?: any;
|
||||
|
||||
/**
|
||||
* If set to `false` then `add`/`addDir` events are also emitted for matching paths while
|
||||
@@ -123,7 +126,7 @@ export interface WatchOptions {
|
||||
useFsEvents?: boolean;
|
||||
|
||||
/**
|
||||
* If relying upon the [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object that
|
||||
* If relying upon the [`fs.Stats`](http://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.
|
||||
*/
|
||||
@@ -183,6 +186,6 @@ export interface AwaitWriteFinishOptions {
|
||||
* produces an instance of `FSWatcher`.
|
||||
*/
|
||||
export function watch(
|
||||
paths: string | ReadonlyArray<string>,
|
||||
paths: string | string[],
|
||||
options?: WatchOptions
|
||||
): FSWatcher;
|
||||
|
||||
Reference in New Issue
Block a user