InclusiveNodeWatchFileSystem.js
6.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chokidar_1 = __importDefault(require("chokidar"));
const path_1 = require("path");
const reporter_1 = require("../reporter");
const minimatch_1 = __importDefault(require("minimatch"));
const BUILTIN_IGNORED_DIRS = ['node_modules', '.git', '.yarn', '.pnp'];
function createIsIgnored(ignored, excluded) {
const ignoredPatterns = ignored ? (Array.isArray(ignored) ? ignored : [ignored]) : [];
const ignoredFunctions = ignoredPatterns.map((pattern) => {
// ensure patterns are valid - see https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/issues/594
if (typeof pattern === 'string') {
return (path) => minimatch_1.default(path, pattern);
}
else if (typeof pattern === 'function') {
return pattern;
}
else if (pattern instanceof RegExp) {
return (path) => pattern.test(path);
}
else {
// fallback to no-ignore function
return () => false;
}
});
ignoredFunctions.push((path) => excluded.some((excludedPath) => path.startsWith(excludedPath)));
ignoredFunctions.push((path) => BUILTIN_IGNORED_DIRS.some((ignoredDir) => path.includes(`/${ignoredDir}/`) || path.includes(`\\${ignoredDir}\\`)));
return function isIgnored(path) {
return ignoredFunctions.some((ignoredFunction) => ignoredFunction(path));
};
}
class InclusiveNodeWatchFileSystem {
constructor(watchFileSystem, compiler, pluginState) {
this.watchFileSystem = watchFileSystem;
this.compiler = compiler;
this.pluginState = pluginState;
this.paused = true;
this.dirsWatchers = new Map();
}
get watcher() {
var _a;
return this.watchFileSystem.watcher || ((_a = this.watchFileSystem.wfs) === null || _a === void 0 ? void 0 : _a.watcher);
}
watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) {
var _a, _b, _c, _d;
reporter_1.clearFilesChange(this.compiler);
const isIgnored = createIsIgnored(options === null || options === void 0 ? void 0 : options.ignored, ((_a = this.pluginState.lastDependencies) === null || _a === void 0 ? void 0 : _a.excluded) || []);
// use standard watch file system for files and missing
const standardWatcher = this.watchFileSystem.watch(files, dirs, missing, startTime, options, callback, callbackUndelayed);
(_b = this.watcher) === null || _b === void 0 ? void 0 : _b.on('change', (file) => {
if (typeof file === 'string' && !isIgnored(file)) {
reporter_1.updateFilesChange(this.compiler, { changedFiles: [file] });
}
});
(_c = this.watcher) === null || _c === void 0 ? void 0 : _c.on('remove', (file) => {
if (typeof file === 'string' && !isIgnored(file)) {
reporter_1.updateFilesChange(this.compiler, { deletedFiles: [file] });
}
});
// calculate what to change
const prevDirs = Array.from(this.dirsWatchers.keys());
const nextDirs = Array.from(((_d = this.pluginState.lastDependencies) === null || _d === void 0 ? void 0 : _d.dirs) || []);
const dirsToUnwatch = prevDirs.filter((prevDir) => !nextDirs.includes(prevDir));
const dirsToWatch = nextDirs.filter((nextDir) => !prevDirs.includes(nextDir) && !isIgnored(nextDir));
// update dirs watcher
dirsToUnwatch.forEach((dirToUnwatch) => {
var _a;
(_a = this.dirsWatchers.get(dirToUnwatch)) === null || _a === void 0 ? void 0 : _a.close();
this.dirsWatchers.delete(dirToUnwatch);
});
dirsToWatch.forEach((dirToWatch) => {
const interval = typeof (options === null || options === void 0 ? void 0 : options.poll) === 'number' ? options.poll : undefined;
const dirWatcher = chokidar_1.default.watch(dirToWatch, {
ignoreInitial: true,
ignorePermissionErrors: true,
ignored: (path) => isIgnored(path),
usePolling: (options === null || options === void 0 ? void 0 : options.poll) ? true : undefined,
interval: interval,
binaryInterval: interval,
alwaysStat: true,
atomic: true,
awaitWriteFinish: true,
});
dirWatcher.on('add', (file, stats) => {
var _a, _b;
if (this.paused) {
return;
}
const extension = path_1.extname(file);
const supportedExtensions = ((_a = this.pluginState.lastDependencies) === null || _a === void 0 ? void 0 : _a.extensions) || [];
if (!supportedExtensions.includes(extension)) {
return;
}
reporter_1.updateFilesChange(this.compiler, { changedFiles: [file] });
const mtime = (stats === null || stats === void 0 ? void 0 : stats.mtimeMs) || (stats === null || stats === void 0 ? void 0 : stats.ctimeMs) || 1;
(_b = this.watcher) === null || _b === void 0 ? void 0 : _b._onChange(dirToWatch, mtime, file, 'rename');
});
dirWatcher.on('unlink', (file) => {
var _a, _b;
if (this.paused) {
return;
}
const extension = path_1.extname(file);
const supportedExtensions = ((_a = this.pluginState.lastDependencies) === null || _a === void 0 ? void 0 : _a.extensions) || [];
if (!supportedExtensions.includes(extension)) {
return;
}
reporter_1.updateFilesChange(this.compiler, { deletedFiles: [file] });
(_b = this.watcher) === null || _b === void 0 ? void 0 : _b._onRemove(dirToWatch, file, 'rename');
});
this.dirsWatchers.set(dirToWatch, dirWatcher);
});
this.paused = false;
return Object.assign(Object.assign({}, standardWatcher), { close: () => {
reporter_1.clearFilesChange(this.compiler);
if (standardWatcher) {
standardWatcher.close();
}
this.dirsWatchers.forEach((dirWatcher) => {
dirWatcher === null || dirWatcher === void 0 ? void 0 : dirWatcher.close();
});
this.dirsWatchers.clear();
this.paused = true;
}, pause: () => {
if (standardWatcher) {
standardWatcher.pause();
}
this.paused = true;
} });
}
}
exports.InclusiveNodeWatchFileSystem = InclusiveNodeWatchFileSystem;