Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(deps): update chokidar to v4 #5374

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ node_modules
examples/**/main.js
examples/client/trusted-types-overlay/app.js
test/fixtures/reload-config/foo.js
test/fixtures/worker-config-dev-server-false/public/worker-bundle.js
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ yarn-error.log

test/fixtures/static-config/public/assets/non-exist.txt
test/fixtures/watch-files-config/public/assets/non-exist.txt
test/fixtures/watch-files-config/public/non-existant/non-exist.txt
test/fixtures/reload-config/main.css
test/fixtures/reload-config-2/main.css
test/fixtures/worker-config-dev-server-false/public
Expand Down
35 changes: 32 additions & 3 deletions lib/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const fs = require("graceful-fs");
const ipaddr = require("ipaddr.js");
const { validate } = require("schema-utils");
const schema = require("./options.json");
const {
getGlobbedWatcherPaths,
getIgnoreMatchers,
} = require("./getGlobMatchers");

/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */
/** @typedef {import("webpack").Compiler} Compiler */
Expand All @@ -18,7 +22,7 @@ const schema = require("./options.json");
/** @typedef {import("webpack").Stats} Stats */
/** @typedef {import("webpack").MultiStats} MultiStats */
/** @typedef {import("os").NetworkInterfaceInfo} NetworkInterfaceInfo */
/** @typedef {import("chokidar").WatchOptions} WatchOptions */
/** @typedef {import("chokidar").ChokidarOptions & { disableGlobbing?: boolean }} WatchOptions */
/** @typedef {import("chokidar").FSWatcher} FSWatcher */
/** @typedef {import("connect-history-api-fallback").Options} ConnectHistoryApiFallbackOptions */
/** @typedef {import("bonjour-service").Bonjour} Bonjour */
Expand Down Expand Up @@ -312,6 +316,19 @@ function useFn(route, fn) {
* @property {typeof useFn} use
*/

/**
* @template {Record<string, any>} T
* @param {T} obj
* @returns {T}
*/
function removeUndefinedValues(obj) {
return /** @type {T} **/ (
Object.fromEntries(
Object.entries(obj).filter(([, value]) => typeof value !== "undefined"),
)
);
}

/**
* @template {BasicApplication} [A=ExpressApplication]
* @template {BasicServer} [S=HTTPServer]
Expand Down Expand Up @@ -3255,9 +3272,21 @@ class Server {
* @param {string | string[]} watchPath
* @param {WatchOptions} [watchOptions]
*/
watchFiles(watchPath, watchOptions) {
watchFiles(watchPath, watchOptions = {}) {
const chokidar = require("chokidar");
const watcher = chokidar.watch(watchPath, watchOptions);

const [watchPaths, ignoreFunction] = getGlobbedWatcherPaths(
watchPath,
watchOptions,
);

watchOptions.ignored = getIgnoreMatchers(watchOptions, ignoreFunction);

const watcher = chokidar.watch(
watchPaths,
// https://github.com/paulmillr/chokidar/issues/1394
removeUndefinedValues(watchOptions),
);

// disabling refreshing on changing the content
if (this.options.liveReload) {
Expand Down
76 changes: 76 additions & 0 deletions lib/getGlobMatchers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"use strict";

module.exports = {
/**
* @param {string[] | string} _watchPaths
* @param {import("./Server").WatchOptions} watchOptions
* @returns {[string[], import("chokidar").MatchFunction | null]}*/
getGlobbedWatcherPaths(_watchPaths, { disableGlobbing, cwd }) {
const watchPaths = Array.isArray(_watchPaths) ? _watchPaths : [_watchPaths];

if (disableGlobbing === true) {
return [watchPaths, null];
}

const picomatch = require("picomatch");
const isGlob = require("is-glob");
const watchPathGlobs = watchPaths.filter((p) => isGlob(p));

if (watchPathGlobs.length === 0) {
return [watchPaths, null];
}

const globParent = require("glob-parent");

watchPathGlobs.forEach((p) => {
watchPaths[watchPaths.indexOf(p)] = globParent(p);
});

const matcher = picomatch(watchPathGlobs, { cwd, dot: true });

/** @type {import("chokidar").MatchFunction} */
const ignoreFunction = (p) => !watchPaths.includes(p) && !matcher(p);

// Ignore all paths that don't match any of the globs
return [watchPaths, ignoreFunction];
},

/**
*
* @param {import("./Server").WatchOptions} watchOptions
* @param {import("chokidar").MatchFunction | null } ignoreFunction
* @returns {import("chokidar").Matcher[]}
*/
getIgnoreMatchers({ disableGlobbing, ignored, cwd }, ignoreFunction) {
const _ignored = /** @type {import("chokidar").Matcher[]}**/ (
typeof ignored === "undefined" ? [] : [ignored]
);
const matchers = Array.isArray(ignored) ? ignored : _ignored;

if (disableGlobbing === true) {
return matchers;
}

if (ignoreFunction) {
matchers.push(ignoreFunction);
}

const picomatch = require("picomatch");
const isGlob = require("is-glob");

// Double filter to satisfy typescript. Otherwise nasty casting is required
const ignoredGlobs = matchers
.filter((s) => typeof s === "string")
.filter((s) => isGlob(s));

if (ignoredGlobs.length === 0) {
return matchers;
}

const matcher = picomatch(ignoredGlobs, { cwd, dot: true });

matchers.push(matcher);

return matchers.filter((s) => typeof s !== "string" || !isGlob(s));
},
};
Loading