reslop 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/LICENSE +1 -1
  3. package/README.md +11 -11
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +32 -19
  6. package/lib/capabilities.js +8 -8
  7. package/lib/cli.js +40 -74
  8. package/lib/clipboard.js +39 -47
  9. package/lib/dashboard/git.js +128 -0
  10. package/lib/dashboard/model.js +332 -0
  11. package/lib/dashboard/npm.js +193 -0
  12. package/lib/dashboard/tree.js +278 -0
  13. package/lib/deps-diff.js +197 -402
  14. package/lib/deps.js +113 -240
  15. package/lib/detect.js +8 -18
  16. package/lib/diff/align.js +41 -113
  17. package/lib/diff/diff.js +12 -43
  18. package/lib/diff/display.js +25 -36
  19. package/lib/diff/edit.js +6 -20
  20. package/lib/diff/inline.js +76 -144
  21. package/lib/diff/items.js +33 -47
  22. package/lib/diff/parse.js +28 -56
  23. package/lib/diff/patch.js +12 -33
  24. package/lib/diff/unit.js +79 -178
  25. package/lib/editor.js +52 -69
  26. package/lib/files.js +71 -89
  27. package/lib/git-branches.js +254 -416
  28. package/lib/git-deps.js +147 -272
  29. package/lib/git-reword-todo.js +5 -13
  30. package/lib/git-worktree.js +141 -212
  31. package/lib/git.js +21 -49
  32. package/lib/github.js +67 -181
  33. package/lib/gitlab.js +40 -90
  34. package/lib/highlight/bash.js +55 -177
  35. package/lib/highlight/core.js +155 -141
  36. package/lib/highlight/css.js +25 -58
  37. package/lib/highlight/csv.js +19 -37
  38. package/lib/highlight/dart.js +72 -213
  39. package/lib/highlight/dot.js +14 -14
  40. package/lib/highlight/html.js +42 -63
  41. package/lib/highlight/js.js +177 -506
  42. package/lib/highlight/json.js +17 -37
  43. package/lib/highlight/log.js +19 -25
  44. package/lib/highlight/txt.js +7 -10
  45. package/lib/highlight.js +17 -46
  46. package/lib/keys.js +49 -82
  47. package/lib/manifest.js +67 -126
  48. package/lib/npm-commands.js +120 -169
  49. package/lib/remote.js +140 -190
  50. package/lib/render/branches.js +63 -61
  51. package/lib/render/chrome.js +220 -333
  52. package/lib/render/commits.js +160 -361
  53. package/lib/render/dash-activity.js +212 -0
  54. package/lib/render/dash-blocks.js +245 -0
  55. package/lib/render/dash-table.js +290 -0
  56. package/lib/render/dashboard.js +62 -0
  57. package/lib/render/diff.js +123 -258
  58. package/lib/render/files.js +40 -85
  59. package/lib/render/frame.js +78 -117
  60. package/lib/render/notes.js +139 -210
  61. package/lib/render/npm.js +213 -177
  62. package/lib/render/present.js +4 -11
  63. package/lib/render/primitives.js +72 -174
  64. package/lib/render/render.js +5 -14
  65. package/lib/render/report.js +43 -0
  66. package/lib/render/tiles.js +260 -0
  67. package/lib/render/unit.js +15 -31
  68. package/lib/report-model.js +110 -33
  69. package/lib/report-parse.js +56 -37
  70. package/lib/report-render.js +102 -59
  71. package/lib/report-run.js +87 -77
  72. package/lib/report-test.js +221 -99
  73. package/lib/report-tools.js +96 -154
  74. package/lib/review-merge.js +33 -41
  75. package/lib/review.js +68 -129
  76. package/lib/runs.js +225 -0
  77. package/lib/select.js +53 -91
  78. package/lib/session/accessors.js +14 -21
  79. package/lib/session/actions.js +61 -43
  80. package/lib/session/branches.js +166 -222
  81. package/lib/session/change-actions.js +49 -119
  82. package/lib/session/commit.js +274 -355
  83. package/lib/session/compose.js +556 -714
  84. package/lib/session/dashboard.js +385 -0
  85. package/lib/session/dispatch.js +162 -170
  86. package/lib/session/files-pane.js +76 -44
  87. package/lib/session/items.js +6 -17
  88. package/lib/session/lifecycle.js +393 -466
  89. package/lib/session/load.js +1 -14
  90. package/lib/session/navigation.js +2 -2
  91. package/lib/session/npm.js +403 -420
  92. package/lib/session/ops.js +5 -13
  93. package/lib/session/pointer.js +16 -14
  94. package/lib/session/progress.js +39 -30
  95. package/lib/session/review.js +1 -3
  96. package/lib/session/tasks.js +276 -235
  97. package/lib/session/templates.js +51 -59
  98. package/lib/session/terminal.js +85 -132
  99. package/lib/session/view.js +47 -81
  100. package/lib/session/watch.js +196 -212
  101. package/lib/session.js +81 -161
  102. package/lib/update.js +44 -111
  103. package/lib/utilities.js +46 -88
  104. package/lib/wrap.js +29 -55
  105. package/package.json +1 -1
@@ -3,7 +3,12 @@
3
3
  const fs = require('node:fs');
4
4
  const path = require('node:path');
5
5
 
6
+ const runs = require('../runs.js');
7
+ const { isRunsRel } = runs;
8
+
6
9
  const DEBOUNCE_MS = 200;
10
+ const UNKNOWN_PATH = '.';
11
+ const MODULES_STAMP = 'node_modules/.package-lock.json';
7
12
 
8
13
  const SKIP_DIRS = ['node_modules', '.review', 'coverage', 'dist', '.cache'];
9
14
 
@@ -14,41 +19,30 @@ const GIT_WATCH_NAMES = [
14
19
  'FETCH_HEAD',
15
20
  'ORIG_HEAD',
16
21
  'refs',
22
+ 'rebase-merge',
23
+ 'rebase-apply',
17
24
  ];
18
25
 
19
- const linuxRecursiveNode = (version) => {
20
- const parts = `${version}`.split('.');
21
- const major = Number(parts[0]);
22
- const minor = Number(parts[1]);
23
- if (major > 19) return true;
24
- return major === 19 && minor >= 1;
25
- };
26
-
27
26
  const canWatchRecursive = (
28
27
  platform = process.platform,
29
28
  version = process.versions.node,
30
29
  ) => {
31
30
  if (platform === 'win32' || platform === 'darwin') return true;
32
- if (platform === 'linux') return linuxRecursiveNode(version);
33
- return false;
31
+ if (platform !== 'linux') return false;
32
+ const [major, minor] = `${version}`.split('.').map(Number);
33
+ return major > 19 || (major === 19 && minor >= 1);
34
34
  };
35
35
 
36
- const ignoredName = (name) => {
37
- if (!name) return false;
38
- if (name.endsWith('.lock')) return true;
39
- if (name.endsWith('~')) return true;
40
- if (name.endsWith('.swp') || name.endsWith('.swo')) return true;
41
- if (name.startsWith('.#')) return true;
42
- if (name === '.DS_Store') return true;
43
- return false;
44
- };
36
+ const IGNORED_SUFFIXES = ['.lock', '~', '.swp', '.swo'];
45
37
 
46
- const ignoredGitRel = (parts) => {
47
- if (parts[1] === 'logs' && parts[2] === 'HEAD') return false;
48
- const name = parts[1] ?? '';
49
- if (!name) return false;
50
- if (GIT_WATCH_NAMES.includes(name)) return false;
51
- return true;
38
+ const ignoredName = (name) =>
39
+ IGNORED_SUFFIXES.some((suffix) => name.endsWith(suffix)) ||
40
+ name.startsWith('.#') ||
41
+ name === '.DS_Store';
42
+
43
+ const ignoredGitRel = ([, name = '', sub]) => {
44
+ if (name === 'logs' && sub === 'HEAD') return false;
45
+ return name !== '' && !GIT_WATCH_NAMES.includes(name);
52
46
  };
53
47
 
54
48
  const slashRel = (rel) => `${rel}`.replaceAll('\\', '/');
@@ -56,34 +50,24 @@ const slashRel = (rel) => `${rel}`.replaceAll('\\', '/');
56
50
  const ignoredRel = (rel) => {
57
51
  const norm = slashRel(rel);
58
52
  if (!norm || norm === '.') return false;
53
+ if (norm === MODULES_STAMP) return false;
59
54
  const parts = norm.split('/');
60
- for (const part of parts) {
61
- if (SKIP_DIRS.includes(part)) return true;
62
- }
55
+ if (parts.some((part) => SKIP_DIRS.includes(part))) return true;
63
56
  if (parts[0] === '.git') return ignoredGitRel(parts);
64
57
  return ignoredName(parts[parts.length - 1]);
65
58
  };
66
59
 
67
60
  const skipDirName = (name) => name === '.git' || SKIP_DIRS.includes(name);
68
61
 
69
- const closeWatcher = (watcher) => {
70
- try {
71
- watcher.close();
72
- } catch {
73
- // already closed
74
- }
75
- };
76
-
77
62
  const reviewMarkdown = (rel) => {
78
- const norm = `${rel}`.replaceAll('\\', '/');
79
- if (!norm.startsWith('.review/')) return false;
80
- const rest = norm.slice('.review/'.length);
63
+ if (!rel.startsWith('.review/')) return false;
64
+ const rest = rel.slice('.review/'.length);
81
65
  if (!rest || rest.includes('/')) return false;
82
66
  return rest.endsWith('.md');
83
67
  };
84
68
 
85
69
  const isReviewDir = (root, dir) => {
86
- const rel = path.relative(root, dir).replaceAll('\\', '/');
70
+ const rel = slashRel(path.relative(root, dir));
87
71
  return rel === '.review' || rel.startsWith('.review/');
88
72
  };
89
73
 
@@ -106,16 +90,15 @@ const isBareReviewName = (root, dir, rel) => {
106
90
  const isReviewEvent = (root, dir, name) => {
107
91
  if (isReviewDir(root, dir)) return true;
108
92
  if (!name) return false;
109
- const rel = path.relative(root, path.join(dir, name));
110
- const norm = rel.replaceAll('\\', '/');
111
- if (reviewMarkdown(norm)) return true;
112
- return isBareReviewName(root, dir, norm);
93
+ const rel = slashRel(path.relative(root, path.join(dir, name)));
94
+ if (reviewMarkdown(rel)) return true;
95
+ return isBareReviewName(root, dir, rel);
113
96
  };
114
97
 
115
98
  const isOwnDirEvent = (dir, name) => {
116
99
  if (!name) return false;
117
100
  const base = path.basename(dir);
118
- const slash = `${name}`.replaceAll('\\', '/');
101
+ const slash = slashRel(name);
119
102
  const bare = slash.startsWith('./') ? slash.slice(2) : slash;
120
103
  const trimmed = bare.endsWith('/') ? bare.slice(0, -1) : bare;
121
104
  if (trimmed === base) {
@@ -144,200 +127,201 @@ const unchangedSince = (full, since) => {
144
127
  }
145
128
  };
146
129
 
147
- const schedule = (state, timerKey, fire) => {
148
- if (state.closed || !fire) return;
149
- if (state[timerKey] !== null) clearTimeout(state[timerKey]);
150
- state[timerKey] = setTimeout(() => {
151
- state[timerKey] = null;
152
- if (state.closed) return;
153
- fire();
154
- }, state.debounceMs);
155
- const timer = state[timerKey];
156
- if (timer && typeof timer.unref === 'function') timer.unref();
157
- };
158
-
159
130
  const REVIEW_HOLD_MS = 200;
160
131
 
161
- const reviewBurst = (state) => {
162
- const seen = state.reviewSeenAt;
163
- if (!seen) return false;
164
- const hold = Math.max(state.debounceMs * 2, REVIEW_HOLD_MS);
165
- return Date.now() - seen < hold;
166
- };
132
+ class DiskWatcher {
133
+ constructor(options) {
134
+ this.root = path.resolve(options.root);
135
+ this.debounceMs = options.debounceMs ?? DEBOUNCE_MS;
136
+ this.onChange = options.onChange;
137
+ this.onReview = options.onReview;
138
+ this.onPaths = options.onPaths;
139
+ this.recursive = options.recursive ?? canWatchRecursive();
140
+ this.watchers = [];
141
+ this.watched = new Set();
142
+ this.files = new Set();
143
+ this.pending = new Set();
144
+ this.timers = { change: null, review: null, loose: null, paths: null };
145
+ this.looseChange = false;
146
+ this.reviewSeenAt = 0;
147
+ this.startedAt = Date.now();
148
+ this.closed = false;
149
+ const scopes = options.paths?.length ? options.paths : ['.'];
150
+ for (const spec of scopes) this.watchScope(spec);
151
+ const gitDir = path.resolve(this.root, '.git');
152
+ this.watchOne(gitDir);
153
+ this.watchOne(path.join(gitDir, 'refs'));
154
+ this.watchOne(path.join(gitDir, 'logs'));
155
+ this.watchOne(path.resolve(this.root, runs.runsDir('.')));
156
+ this.watchOne(path.resolve(this.root, '.review'));
157
+ }
167
158
 
168
- const scheduleChange = (state, loose = false) => {
169
- state.looseChange = loose && (state.timer === null || state.looseChange);
170
- schedule(state, 'timer', () => {
171
- if (state.looseChange && reviewBurst(state)) return;
172
- if (state.onChange) state.onChange();
173
- });
174
- };
159
+ schedule(key, fire) {
160
+ if (this.closed || !fire) return;
161
+ this.clearTimer(key);
162
+ this.timers[key] = setTimeout(() => {
163
+ this.timers[key] = null;
164
+ if (!this.closed) fire();
165
+ }, this.debounceMs);
166
+ this.timers[key].unref();
167
+ }
175
168
 
176
- const scheduleUnnamed = (state) => {
177
- if (reviewBurst(state)) return;
178
- schedule(state, 'looseTimer', () => {
179
- if (!reviewBurst(state)) scheduleChange(state, true);
180
- });
181
- };
169
+ clearTimer(key) {
170
+ if (this.timers[key] !== null) clearTimeout(this.timers[key]);
171
+ this.timers[key] = null;
172
+ }
182
173
 
183
- const clearTimer = (state, timerKey) => {
184
- if (state[timerKey] !== null) clearTimeout(state[timerKey]);
185
- state[timerKey] = null;
186
- };
174
+ reviewBurst() {
175
+ if (!this.reviewSeenAt) return false;
176
+ const hold = Math.max(this.debounceMs * 2, REVIEW_HOLD_MS);
177
+ return Date.now() - this.reviewSeenAt < hold;
178
+ }
187
179
 
188
- const dropLooseChange = (state) => {
189
- clearTimer(state, 'looseTimer');
190
- if (state.looseChange) clearTimer(state, 'timer');
191
- };
180
+ flushPaths() {
181
+ if (!this.pending.size) return;
182
+ const list = [...this.pending];
183
+ this.pending.clear();
184
+ if (this.onPaths) this.onPaths(list);
185
+ }
192
186
 
193
- const handleWatchEvent = (state, dir, eventType, filename) => {
194
- if (state.closed) return;
195
- const name = filename ? `${filename}` : '';
196
- const rel = name
197
- ? slashRel(path.relative(state.root, path.join(dir, name)))
198
- : '';
199
- const wanted = state.files.has(rel);
200
- if (isReviewEvent(state.root, dir, name)) {
201
- state.reviewSeenAt = Date.now();
202
- dropLooseChange(state);
203
- schedule(state, 'reviewTimer', state.onReview);
204
- if (!wanted) return;
187
+ scheduleChange(loose = false) {
188
+ const idle = this.timers.change === null;
189
+ this.looseChange = loose && (idle || this.looseChange);
190
+ this.schedule('change', () => {
191
+ if (this.looseChange && this.reviewBurst()) return;
192
+ this.flushPaths();
193
+ if (this.onChange) this.onChange();
194
+ });
205
195
  }
206
- if (!name) return void scheduleUnnamed(state);
207
- if (!wanted && ignoredRel(rel)) return;
208
- if (isOwnDirEvent(dir, name)) return;
209
- const full = path.join(dir, name);
210
- if (unchangedSince(full, state.startedAt)) return;
211
- if (eventType === 'rename') state.watchNewDir(full);
212
- scheduleChange(state);
213
- };
214
196
 
215
- const watchOne = (state, target, extra = {}) => {
216
- if (state.closed) return;
217
- if (state.watched.has(target)) return;
218
- try {
219
- const onEvent = (eventType, filename) => {
220
- handleWatchEvent(state, target, eventType, filename);
221
- };
222
- const watcher = fs.watch(
223
- target,
224
- { persistent: false, encoding: 'utf8', ...extra },
225
- onEvent,
226
- );
227
- if (typeof watcher.on === 'function') {
228
- watcher.on('error', () => {});
229
- }
230
- state.watched.add(target);
231
- state.watchers.push(watcher);
232
- } catch {
233
- // missing path or too many watchers
197
+ scheduleUnnamed() {
198
+ if (this.reviewBurst()) return;
199
+ this.pending.add(UNKNOWN_PATH);
200
+ this.schedule('loose', () => {
201
+ if (!this.reviewBurst()) this.scheduleChange(true);
202
+ });
234
203
  }
235
- };
236
204
 
237
- const watchTree = (state, dir) => {
238
- watchOne(state, dir, state.dirWatchOpts);
239
- if (state.recursive) return;
240
- let entries;
241
- try {
242
- entries = fs.readdirSync(dir, { withFileTypes: true });
243
- } catch {
244
- return;
205
+ dropLooseChange() {
206
+ this.clearTimer('loose');
207
+ if (this.looseChange) this.clearTimer('change');
245
208
  }
246
- for (const entry of entries) {
247
- if (!entry.isDirectory()) continue;
248
- if (skipDirName(entry.name)) continue;
249
- watchTree(state, path.join(dir, entry.name));
209
+
210
+ onEvent(dir, eventType, filename) {
211
+ if (this.closed) return;
212
+ const name = filename ? `${filename}` : '';
213
+ const rel = name
214
+ ? slashRel(path.relative(this.root, path.join(dir, name)))
215
+ : '';
216
+ const wanted = this.files.has(rel);
217
+ if (isRunsRel(rel)) {
218
+ this.pending.add(rel);
219
+ if (name && eventType === 'rename') {
220
+ this.watchNewDir(path.join(dir, name));
221
+ }
222
+ return void this.schedule('paths', () => this.flushPaths());
223
+ }
224
+ if (isReviewEvent(this.root, dir, name)) {
225
+ this.reviewSeenAt = Date.now();
226
+ this.dropLooseChange();
227
+ this.schedule('review', this.onReview);
228
+ if (!wanted) return;
229
+ }
230
+ if (!name) return void this.scheduleUnnamed();
231
+ if (!wanted && ignoredRel(rel)) return;
232
+ if (isOwnDirEvent(dir, name)) return;
233
+ const full = path.join(dir, name);
234
+ if (unchangedSince(full, this.startedAt)) return;
235
+ if (eventType === 'rename') this.watchNewDir(full);
236
+ this.pending.add(rel);
237
+ this.scheduleChange();
250
238
  }
251
- };
252
239
 
253
- const maybeWatchNewDir = (state, full) => {
254
- if (state.recursive) return;
255
- let stat;
256
- try {
257
- stat = fs.statSync(full);
258
- } catch {
259
- return;
240
+ watchOne(target, recursive = false) {
241
+ if (this.closed || this.watched.has(target)) return;
242
+ try {
243
+ const options = { persistent: false, encoding: 'utf8', recursive };
244
+ const watcher = fs.watch(target, options, (eventType, filename) => {
245
+ this.onEvent(target, eventType, filename);
246
+ });
247
+ watcher.on('error', () => {});
248
+ this.watched.add(target);
249
+ this.watchers.push(watcher);
250
+ } catch {
251
+ // missing path or too many watchers
252
+ }
260
253
  }
261
- if (!stat.isDirectory()) return;
262
- if (path.basename(full) === '.review') return void watchOne(state, full);
263
- if (skipDirName(path.basename(full))) return;
264
- watchTree(state, full);
265
- };
266
254
 
267
- const watchScope = (state, spec) => {
268
- const target = path.resolve(state.root, spec);
269
- let stat;
270
- try {
271
- stat = fs.statSync(target);
272
- } catch {
273
- return void watchOne(state, path.dirname(target));
255
+ watchTree(dir) {
256
+ this.watchOne(dir, this.recursive);
257
+ if (this.recursive) return;
258
+ let entries;
259
+ try {
260
+ entries = fs.readdirSync(dir, { withFileTypes: true });
261
+ } catch {
262
+ return;
263
+ }
264
+ for (const entry of entries) {
265
+ if (!entry.isDirectory() || skipDirName(entry.name)) continue;
266
+ this.watchTree(path.join(dir, entry.name));
267
+ }
274
268
  }
275
- if (stat.isDirectory()) return void watchTree(state, target);
276
- watchOne(state, path.dirname(target));
277
- };
278
269
 
279
- const watchGit = (state) => {
280
- const gitDir = path.resolve(state.root, '.git');
281
- watchOne(state, gitDir);
282
- watchOne(state, path.resolve(gitDir, 'refs'));
283
- watchOne(state, path.resolve(gitDir, 'logs'));
284
- };
270
+ watchNewDir(full) {
271
+ if (this.recursive) return;
272
+ try {
273
+ if (!fs.statSync(full).isDirectory()) return;
274
+ } catch {
275
+ return;
276
+ }
277
+ const name = path.basename(full);
278
+ if (name === '.review') this.watchOne(full);
279
+ else if (!skipDirName(name)) this.watchTree(full);
280
+ }
285
281
 
286
- const stopState = (state) => {
287
- state.closed = true;
288
- clearTimer(state, 'timer');
289
- clearTimer(state, 'reviewTimer');
290
- clearTimer(state, 'looseTimer');
291
- while (state.watchers.length) closeWatcher(state.watchers.pop());
292
- state.watched.clear();
293
- };
282
+ watchScope(spec) {
283
+ const target = path.resolve(this.root, spec);
284
+ try {
285
+ if (fs.statSync(target).isDirectory()) return void this.watchTree(target);
286
+ } catch {
287
+ // watch the parent until the path appears
288
+ }
289
+ this.watchOne(path.dirname(target));
290
+ }
294
291
 
295
- const watchFiles = (state, rels) => {
296
- state.files = new Set();
297
- for (const rel of rels) {
298
- if (!rel) continue;
299
- const full = path.resolve(state.root, rel);
300
- state.files.add(slashRel(path.relative(state.root, full)));
301
- watchOne(state, path.dirname(full));
292
+ watchFiles(rels) {
293
+ this.files = new Set();
294
+ for (const rel of rels) {
295
+ if (!rel) continue;
296
+ const full = path.resolve(this.root, rel);
297
+ this.files.add(slashRel(path.relative(this.root, full)));
298
+ this.watchOne(path.dirname(full));
299
+ }
302
300
  }
303
- };
304
301
 
305
- const createDiskWatcher = (options) => {
306
- const recursive = options.recursive ?? canWatchRecursive();
307
- const state = {
308
- root: path.resolve(options.root),
309
- debounceMs: options.debounceMs ?? DEBOUNCE_MS,
310
- onChange: options.onChange,
311
- recursive,
312
- dirWatchOpts: recursive ? { recursive: true } : {},
313
- watchers: [],
314
- watched: new Set(),
315
- files: new Set(),
316
- onReview: options.onReview,
317
- timer: null,
318
- reviewTimer: null,
319
- looseTimer: null,
320
- looseChange: false,
321
- reviewSeenAt: 0,
322
- startedAt: Date.now(),
323
- closed: false,
324
- watchNewDir: (full) => maybeWatchNewDir(state, full),
325
- };
326
- const scopes = options.paths && options.paths.length ? options.paths : ['.'];
327
- for (const spec of scopes) watchScope(state, spec);
328
- watchGit(state);
329
- watchOne(state, path.resolve(state.root, '.review'));
330
- return {
331
- close: () => stopState(state),
332
- watchFiles: (rels) => watchFiles(state, rels),
333
- };
334
- };
302
+ close() {
303
+ this.closed = true;
304
+ for (const key of Object.keys(this.timers)) this.clearTimer(key);
305
+ this.pending.clear();
306
+ for (const watcher of this.watchers) {
307
+ try {
308
+ watcher.close();
309
+ } catch {
310
+ // already closed
311
+ }
312
+ }
313
+ this.watchers = [];
314
+ this.watched.clear();
315
+ }
316
+ }
335
317
 
336
318
  module.exports = {
337
319
  DEBOUNCE_MS,
320
+ UNKNOWN_PATH,
321
+ MODULES_STAMP,
338
322
  canWatchRecursive,
339
323
  ignoredRel,
340
324
  isOwnDirEvent,
341
325
  unchangedSince,
342
- createDiskWatcher,
326
+ DiskWatcher,
343
327
  };