InclusiveNodeWatchFileSystem.js 6.8 KB

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