@jsenv/filesystem 4.3.0 → 4.3.1
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,7 @@ 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 fsWatchSupportsRecursive =
|
|
11
|
+
const fsWatchSupportsRecursive = process.platform !== "linux";
|
|
12
12
|
|
|
13
13
|
export const registerDirectoryLifecycle = (
|
|
14
14
|
source,
|
|
@@ -91,8 +91,8 @@ export const registerDirectoryLifecycle = (
|
|
|
91
91
|
try {
|
|
92
92
|
const relativeUrl = urlToRelativeUrl(url, source);
|
|
93
93
|
const previousInfo = infoMap.get(relativeUrl);
|
|
94
|
-
const
|
|
95
|
-
const type = statsToType(
|
|
94
|
+
const stat = statSync(new URL(url));
|
|
95
|
+
const type = statsToType(stat);
|
|
96
96
|
const patternValue = previousInfo
|
|
97
97
|
? previousInfo.patternValue
|
|
98
98
|
: getWatchPatternValue({ url, type });
|
|
@@ -101,13 +101,15 @@ export const registerDirectoryLifecycle = (
|
|
|
101
101
|
url,
|
|
102
102
|
relativeUrl,
|
|
103
103
|
type,
|
|
104
|
-
|
|
105
|
-
mtimeMs: stats.mtimeMs,
|
|
104
|
+
stat,
|
|
106
105
|
patternValue,
|
|
107
106
|
};
|
|
108
107
|
} catch (e) {
|
|
109
108
|
if (e.code === "ENOENT") {
|
|
110
|
-
return
|
|
109
|
+
return {
|
|
110
|
+
type: null,
|
|
111
|
+
stat: null,
|
|
112
|
+
};
|
|
111
113
|
}
|
|
112
114
|
throw e;
|
|
113
115
|
}
|
|
@@ -180,7 +182,7 @@ export const registerDirectoryLifecycle = (
|
|
|
180
182
|
const handleChange = (relativeUrl) => {
|
|
181
183
|
const entryUrl = new URL(relativeUrl, sourceUrl).href;
|
|
182
184
|
const entryInfo = readEntryInfo(entryUrl);
|
|
183
|
-
if (
|
|
185
|
+
if (entryInfo.type === null) {
|
|
184
186
|
const previousEntryInfo = infoMap.get(relativeUrl);
|
|
185
187
|
if (!previousEntryInfo) {
|
|
186
188
|
// on MacOS it's possible to receive a "rename" event for
|
|
@@ -240,7 +242,7 @@ export const registerDirectoryLifecycle = (
|
|
|
240
242
|
readdirSync(new URL(directoryUrl)).forEach((entryName) => {
|
|
241
243
|
const childEntryUrl = new URL(entryName, directoryUrl).href;
|
|
242
244
|
const childEntryInfo = readEntryInfo(childEntryUrl);
|
|
243
|
-
if (childEntryInfo && childEntryInfo.patternValue) {
|
|
245
|
+
if (childEntryInfo.type !== null && childEntryInfo.patternValue) {
|
|
244
246
|
handleEntryFound(childEntryInfo, { notify });
|
|
245
247
|
}
|
|
246
248
|
});
|
|
@@ -269,7 +271,7 @@ export const registerDirectoryLifecycle = (
|
|
|
269
271
|
relativeUrl: entryInfo.relativeUrl,
|
|
270
272
|
type: entryInfo.type,
|
|
271
273
|
patternValue: entryInfo.patternValue,
|
|
272
|
-
mtime: entryInfo.mtimeMs,
|
|
274
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
273
275
|
});
|
|
274
276
|
}
|
|
275
277
|
};
|
|
@@ -280,19 +282,19 @@ export const registerDirectoryLifecycle = (
|
|
|
280
282
|
relativeUrl: entryInfo.relativeUrl,
|
|
281
283
|
type: entryInfo.type,
|
|
282
284
|
patternValue: entryInfo.patternValue,
|
|
283
|
-
mtime: entryInfo.mtimeMs,
|
|
285
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
284
286
|
});
|
|
285
287
|
}
|
|
286
288
|
};
|
|
287
289
|
const handleEntryUpdated = (entryInfo) => {
|
|
288
290
|
infoMap.set(entryInfo.relativeUrl, entryInfo);
|
|
289
|
-
if (updated && entryInfo.patternValue) {
|
|
291
|
+
if (updated && entryInfo.patternValue && shouldCallUpdated(entryInfo)) {
|
|
290
292
|
updated({
|
|
291
293
|
relativeUrl: entryInfo.relativeUrl,
|
|
292
294
|
type: entryInfo.type,
|
|
293
295
|
patternValue: entryInfo.patternValue,
|
|
294
|
-
mtime: entryInfo.mtimeMs,
|
|
295
|
-
previousMtime: entryInfo.previousInfo.mtimeMs,
|
|
296
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
297
|
+
previousMtime: entryInfo.previousInfo.stat.mtimeMs,
|
|
296
298
|
});
|
|
297
299
|
}
|
|
298
300
|
};
|
|
@@ -300,7 +302,7 @@ export const registerDirectoryLifecycle = (
|
|
|
300
302
|
readdirSync(new URL(sourceUrl)).forEach((entry) => {
|
|
301
303
|
const entryUrl = new URL(entry, sourceUrl).href;
|
|
302
304
|
const entryInfo = readEntryInfo(entryUrl);
|
|
303
|
-
if (entryInfo && entryInfo.patternValue) {
|
|
305
|
+
if (entryInfo.type !== null && entryInfo.patternValue) {
|
|
304
306
|
handleEntryFound(entryInfo, {
|
|
305
307
|
notify: notifyExistent,
|
|
306
308
|
});
|
|
@@ -334,6 +336,20 @@ ${relativeUrls.join("\n")}`,
|
|
|
334
336
|
return tracker.cleanup;
|
|
335
337
|
};
|
|
336
338
|
|
|
339
|
+
const shouldCallUpdated = (entryInfo) => {
|
|
340
|
+
const { stat, previousInfo } = entryInfo;
|
|
341
|
+
if (!stat.atimeMs) {
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
if (stat.atimeMs < stat.mtimeMs) {
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
if (stat.mtimeMs > previousInfo.stat.mtimeMs) {
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
return false;
|
|
351
|
+
};
|
|
352
|
+
|
|
337
353
|
const undefinedOrFunction = (value) => {
|
|
338
354
|
return typeof value === "undefined" || typeof value === "function";
|
|
339
355
|
};
|
|
@@ -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
|
+
};
|