@jsenv/filesystem 4.3.0 → 4.3.2
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.
package/package.json
CHANGED
|
@@ -16,7 +16,9 @@ export const createWatcher = (sourcePath, options) => {
|
|
|
16
16
|
if (e.code === "ENOENT") {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
console.error(
|
|
19
|
+
console.error(
|
|
20
|
+
`error while trying to get rid of windows EPERM: ${e.stack}`,
|
|
21
|
+
);
|
|
20
22
|
throw error;
|
|
21
23
|
}
|
|
22
24
|
} else {
|
|
@@ -8,7 +8,8 @@ import { guardTooFastSecondCallPerFile } from "./internal/guard_second_call.js";
|
|
|
8
8
|
import { createWatcher } from "./internal/createWatcher.js";
|
|
9
9
|
import { trackResources } from "./internal/track_resources.js";
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const isLinux = process.platform === "linux";
|
|
12
|
+
const fsWatchSupportsRecursive = !isLinux;
|
|
12
13
|
|
|
13
14
|
export const registerDirectoryLifecycle = (
|
|
14
15
|
source,
|
|
@@ -91,8 +92,8 @@ export const registerDirectoryLifecycle = (
|
|
|
91
92
|
try {
|
|
92
93
|
const relativeUrl = urlToRelativeUrl(url, source);
|
|
93
94
|
const previousInfo = infoMap.get(relativeUrl);
|
|
94
|
-
const
|
|
95
|
-
const type = statsToType(
|
|
95
|
+
const stat = statSync(new URL(url));
|
|
96
|
+
const type = statsToType(stat);
|
|
96
97
|
const patternValue = previousInfo
|
|
97
98
|
? previousInfo.patternValue
|
|
98
99
|
: getWatchPatternValue({ url, type });
|
|
@@ -101,13 +102,15 @@ export const registerDirectoryLifecycle = (
|
|
|
101
102
|
url,
|
|
102
103
|
relativeUrl,
|
|
103
104
|
type,
|
|
104
|
-
|
|
105
|
-
mtimeMs: stats.mtimeMs,
|
|
105
|
+
stat,
|
|
106
106
|
patternValue,
|
|
107
107
|
};
|
|
108
108
|
} catch (e) {
|
|
109
109
|
if (e.code === "ENOENT") {
|
|
110
|
-
return
|
|
110
|
+
return {
|
|
111
|
+
type: null,
|
|
112
|
+
stat: null,
|
|
113
|
+
};
|
|
111
114
|
}
|
|
112
115
|
throw e;
|
|
113
116
|
}
|
|
@@ -180,7 +183,7 @@ export const registerDirectoryLifecycle = (
|
|
|
180
183
|
const handleChange = (relativeUrl) => {
|
|
181
184
|
const entryUrl = new URL(relativeUrl, sourceUrl).href;
|
|
182
185
|
const entryInfo = readEntryInfo(entryUrl);
|
|
183
|
-
if (
|
|
186
|
+
if (entryInfo.type === null) {
|
|
184
187
|
const previousEntryInfo = infoMap.get(relativeUrl);
|
|
185
188
|
if (!previousEntryInfo) {
|
|
186
189
|
// on MacOS it's possible to receive a "rename" event for
|
|
@@ -240,7 +243,7 @@ export const registerDirectoryLifecycle = (
|
|
|
240
243
|
readdirSync(new URL(directoryUrl)).forEach((entryName) => {
|
|
241
244
|
const childEntryUrl = new URL(entryName, directoryUrl).href;
|
|
242
245
|
const childEntryInfo = readEntryInfo(childEntryUrl);
|
|
243
|
-
if (childEntryInfo && childEntryInfo.patternValue) {
|
|
246
|
+
if (childEntryInfo.type !== null && childEntryInfo.patternValue) {
|
|
244
247
|
handleEntryFound(childEntryInfo, { notify });
|
|
245
248
|
}
|
|
246
249
|
});
|
|
@@ -269,7 +272,7 @@ export const registerDirectoryLifecycle = (
|
|
|
269
272
|
relativeUrl: entryInfo.relativeUrl,
|
|
270
273
|
type: entryInfo.type,
|
|
271
274
|
patternValue: entryInfo.patternValue,
|
|
272
|
-
mtime: entryInfo.mtimeMs,
|
|
275
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
273
276
|
});
|
|
274
277
|
}
|
|
275
278
|
};
|
|
@@ -280,19 +283,19 @@ export const registerDirectoryLifecycle = (
|
|
|
280
283
|
relativeUrl: entryInfo.relativeUrl,
|
|
281
284
|
type: entryInfo.type,
|
|
282
285
|
patternValue: entryInfo.patternValue,
|
|
283
|
-
mtime: entryInfo.mtimeMs,
|
|
286
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
284
287
|
});
|
|
285
288
|
}
|
|
286
289
|
};
|
|
287
290
|
const handleEntryUpdated = (entryInfo) => {
|
|
288
291
|
infoMap.set(entryInfo.relativeUrl, entryInfo);
|
|
289
|
-
if (updated && entryInfo.patternValue) {
|
|
292
|
+
if (updated && entryInfo.patternValue && shouldCallUpdated(entryInfo)) {
|
|
290
293
|
updated({
|
|
291
294
|
relativeUrl: entryInfo.relativeUrl,
|
|
292
295
|
type: entryInfo.type,
|
|
293
296
|
patternValue: entryInfo.patternValue,
|
|
294
|
-
mtime: entryInfo.mtimeMs,
|
|
295
|
-
previousMtime: entryInfo.previousInfo.mtimeMs,
|
|
297
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
298
|
+
previousMtime: entryInfo.previousInfo.stat.mtimeMs,
|
|
296
299
|
});
|
|
297
300
|
}
|
|
298
301
|
};
|
|
@@ -300,7 +303,7 @@ export const registerDirectoryLifecycle = (
|
|
|
300
303
|
readdirSync(new URL(sourceUrl)).forEach((entry) => {
|
|
301
304
|
const entryUrl = new URL(entry, sourceUrl).href;
|
|
302
305
|
const entryInfo = readEntryInfo(entryUrl);
|
|
303
|
-
if (entryInfo && entryInfo.patternValue) {
|
|
306
|
+
if (entryInfo.type !== null && entryInfo.patternValue) {
|
|
304
307
|
handleEntryFound(entryInfo, {
|
|
305
308
|
notify: notifyExistent,
|
|
306
309
|
});
|
|
@@ -334,6 +337,20 @@ ${relativeUrls.join("\n")}`,
|
|
|
334
337
|
return tracker.cleanup;
|
|
335
338
|
};
|
|
336
339
|
|
|
340
|
+
const shouldCallUpdated = (entryInfo) => {
|
|
341
|
+
const { stat, previousInfo } = entryInfo;
|
|
342
|
+
if (!stat.atimeMs) {
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
if (stat.atimeMs < stat.mtimeMs) {
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
if (isLinux && stat.mtimeMs <= previousInfo.stat.mtimeMs) {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
return true;
|
|
352
|
+
};
|
|
353
|
+
|
|
337
354
|
const undefinedOrFunction = (value) => {
|
|
338
355
|
return typeof value === "undefined" || typeof value === "function";
|
|
339
356
|
};
|
|
@@ -47,7 +47,7 @@ export const registerFileLifecycle = (
|
|
|
47
47
|
|
|
48
48
|
const tracker = trackResources();
|
|
49
49
|
|
|
50
|
-
const handleFileFound = ({ existent }) => {
|
|
50
|
+
const handleFileFound = ({ stat, existent }) => {
|
|
51
51
|
const fileMutationStopWatching = watchFileMutation(sourceUrl, {
|
|
52
52
|
updated,
|
|
53
53
|
removed: () => {
|
|
@@ -58,6 +58,7 @@ export const registerFileLifecycle = (
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
keepProcessAlive,
|
|
61
|
+
stat,
|
|
61
62
|
});
|
|
62
63
|
const fileMutationStopTracking = tracker.registerCleanupCallback(
|
|
63
64
|
fileMutationStopWatching,
|
|
@@ -77,9 +78,9 @@ export const registerFileLifecycle = (
|
|
|
77
78
|
const watchFileAdded = () => {
|
|
78
79
|
const fileCreationStopWatching = watchFileCreation(
|
|
79
80
|
sourceUrl,
|
|
80
|
-
() => {
|
|
81
|
+
(stat) => {
|
|
81
82
|
fileCreationgStopTracking();
|
|
82
|
-
handleFileFound({ existent: false });
|
|
83
|
+
handleFileFound({ stat, existent: false });
|
|
83
84
|
},
|
|
84
85
|
keepProcessAlive,
|
|
85
86
|
);
|
|
@@ -88,8 +89,8 @@ export const registerFileLifecycle = (
|
|
|
88
89
|
);
|
|
89
90
|
};
|
|
90
91
|
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
92
|
+
const { type, stat } = readFileInfo(sourceUrl);
|
|
93
|
+
if (type === null) {
|
|
93
94
|
if (added) {
|
|
94
95
|
watchFileAdded();
|
|
95
96
|
} else {
|
|
@@ -97,8 +98,8 @@ export const registerFileLifecycle = (
|
|
|
97
98
|
`${urlToFileSystemPath(sourceUrl)} must lead to a file, found nothing`,
|
|
98
99
|
);
|
|
99
100
|
}
|
|
100
|
-
} else if (
|
|
101
|
-
handleFileFound({ existent: true });
|
|
101
|
+
} else if (type === "file") {
|
|
102
|
+
handleFileFound({ stat, existent: true });
|
|
102
103
|
} else {
|
|
103
104
|
throw new Error(
|
|
104
105
|
`${urlToFileSystemPath(
|
|
@@ -110,13 +111,19 @@ export const registerFileLifecycle = (
|
|
|
110
111
|
return tracker.cleanup;
|
|
111
112
|
};
|
|
112
113
|
|
|
113
|
-
const
|
|
114
|
+
const readFileInfo = (url) => {
|
|
114
115
|
try {
|
|
115
|
-
const
|
|
116
|
-
return
|
|
116
|
+
const stat = statSync(new URL(url));
|
|
117
|
+
return {
|
|
118
|
+
type: statsToType(stat),
|
|
119
|
+
stat,
|
|
120
|
+
};
|
|
117
121
|
} catch (e) {
|
|
118
122
|
if (e.code === "ENOENT") {
|
|
119
|
-
return
|
|
123
|
+
return {
|
|
124
|
+
type: null,
|
|
125
|
+
stat: null,
|
|
126
|
+
};
|
|
120
127
|
}
|
|
121
128
|
throw e;
|
|
122
129
|
}
|
|
@@ -135,14 +142,15 @@ const watchFileCreation = (source, callback, keepProcessAlive) => {
|
|
|
135
142
|
directoryWatcher.on("change", (eventType, filename) => {
|
|
136
143
|
if (filename && filename !== sourceFilename) return;
|
|
137
144
|
|
|
138
|
-
const type =
|
|
145
|
+
const { type, stat } = readFileInfo(source);
|
|
139
146
|
// ignore if something else with that name gets created
|
|
140
147
|
// we are only interested into files
|
|
141
|
-
if (type !== "file")
|
|
142
|
-
|
|
148
|
+
if (type !== "file") {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
143
151
|
directoryWatcher.close();
|
|
144
152
|
directoryWatcher = undefined;
|
|
145
|
-
callback();
|
|
153
|
+
callback(stat);
|
|
146
154
|
});
|
|
147
155
|
|
|
148
156
|
return () => {
|
|
@@ -154,26 +162,28 @@ const watchFileCreation = (source, callback, keepProcessAlive) => {
|
|
|
154
162
|
|
|
155
163
|
const watchFileMutation = (
|
|
156
164
|
sourceUrl,
|
|
157
|
-
{ updated, removed, keepProcessAlive },
|
|
165
|
+
{ updated, removed, keepProcessAlive, stat },
|
|
158
166
|
) => {
|
|
167
|
+
let prevStat = stat;
|
|
159
168
|
let watcher = createWatcher(urlToFileSystemPath(sourceUrl), {
|
|
160
169
|
persistent: keepProcessAlive,
|
|
161
170
|
});
|
|
162
171
|
|
|
163
172
|
watcher.on("change", () => {
|
|
164
|
-
const
|
|
173
|
+
const { type, stat } = readFileInfo(sourceUrl);
|
|
165
174
|
|
|
166
|
-
if (
|
|
175
|
+
if (type === null) {
|
|
167
176
|
watcher.close();
|
|
168
177
|
watcher = undefined;
|
|
169
178
|
if (removed) {
|
|
170
179
|
removed();
|
|
171
180
|
}
|
|
172
|
-
} else if (
|
|
173
|
-
if (updated) {
|
|
181
|
+
} else if (type === "file") {
|
|
182
|
+
if (updated && shouldCallUpdated(stat, prevStat)) {
|
|
174
183
|
updated();
|
|
175
184
|
}
|
|
176
185
|
}
|
|
186
|
+
prevStat = stat;
|
|
177
187
|
});
|
|
178
188
|
|
|
179
189
|
return () => {
|
|
@@ -182,3 +192,16 @@ const watchFileMutation = (
|
|
|
182
192
|
}
|
|
183
193
|
};
|
|
184
194
|
};
|
|
195
|
+
|
|
196
|
+
const shouldCallUpdated = (stat, prevStat) => {
|
|
197
|
+
if (!stat.atimeMs) {
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
if (stat.atimeMs < stat.mtimeMs) {
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
if (stat.mtimeMs > prevStat.mtimeMs) {
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
return false;
|
|
207
|
+
};
|