@jsenv/core 39.7.6 → 39.7.7
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/dist/jsenv_core.js
CHANGED
|
@@ -3,7 +3,7 @@ import os, { networkInterfaces } from "node:os";
|
|
|
3
3
|
import tty from "node:tty";
|
|
4
4
|
import stringWidth from "string-width";
|
|
5
5
|
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
6
|
-
import { readdir, chmod, stat, lstat, chmodSync, statSync, lstatSync, promises, readFileSync, writeFileSync as writeFileSync$1, mkdirSync, unlink, openSync, closeSync, rmdir,
|
|
6
|
+
import { readdir, chmod, stat, lstat, chmodSync, statSync, lstatSync, promises, readFileSync, writeFileSync as writeFileSync$1, mkdirSync, unlink, openSync, closeSync, rmdir, unlinkSync, readdirSync, rmdirSync, watch, createReadStream, readFile, existsSync, realpathSync } from "node:fs";
|
|
7
7
|
import { extname } from "node:path";
|
|
8
8
|
import crypto, { createHash } from "node:crypto";
|
|
9
9
|
import cluster from "node:cluster";
|
|
@@ -3668,7 +3668,7 @@ const removeEntry = async (
|
|
|
3668
3668
|
sourceStats.isCharacterDevice() ||
|
|
3669
3669
|
sourceStats.isBlockDevice()
|
|
3670
3670
|
) {
|
|
3671
|
-
await removeNonDirectory(
|
|
3671
|
+
await removeNonDirectory$1(
|
|
3672
3672
|
sourceUrl.endsWith("/") ? sourceUrl.slice(0, -1) : sourceUrl,
|
|
3673
3673
|
{
|
|
3674
3674
|
maxRetries,
|
|
@@ -3689,7 +3689,7 @@ const removeEntry = async (
|
|
|
3689
3689
|
}
|
|
3690
3690
|
};
|
|
3691
3691
|
|
|
3692
|
-
const removeNonDirectory = (sourceUrl, { maxRetries, retryDelay }) => {
|
|
3692
|
+
const removeNonDirectory$1 = (sourceUrl, { maxRetries, retryDelay }) => {
|
|
3693
3693
|
const sourcePath = urlToFileSystemPath(sourceUrl);
|
|
3694
3694
|
|
|
3695
3695
|
let retryCount = 0;
|
|
@@ -3828,11 +3828,11 @@ const removeDirectory = async (
|
|
|
3828
3828
|
};
|
|
3829
3829
|
|
|
3830
3830
|
const visitFile = async (fileUrl) => {
|
|
3831
|
-
await removeNonDirectory(fileUrl, { maxRetries, retryDelay });
|
|
3831
|
+
await removeNonDirectory$1(fileUrl, { maxRetries, retryDelay });
|
|
3832
3832
|
};
|
|
3833
3833
|
|
|
3834
3834
|
const visitSymbolicLink = async (symbolicLinkUrl) => {
|
|
3835
|
-
await removeNonDirectory(symbolicLinkUrl, { maxRetries, retryDelay });
|
|
3835
|
+
await removeNonDirectory$1(symbolicLinkUrl, { maxRetries, retryDelay });
|
|
3836
3836
|
};
|
|
3837
3837
|
|
|
3838
3838
|
try {
|
|
@@ -3877,6 +3877,204 @@ const removeDirectoryNaive = (
|
|
|
3877
3877
|
|
|
3878
3878
|
process.platform === "win32";
|
|
3879
3879
|
|
|
3880
|
+
const removeEntrySync = (
|
|
3881
|
+
source,
|
|
3882
|
+
{
|
|
3883
|
+
allowUseless = false,
|
|
3884
|
+
recursive = false,
|
|
3885
|
+
maxRetries = 3,
|
|
3886
|
+
retryDelay = 100,
|
|
3887
|
+
onlyContent = false,
|
|
3888
|
+
} = {},
|
|
3889
|
+
) => {
|
|
3890
|
+
const sourceUrl = assertAndNormalizeFileUrl(source);
|
|
3891
|
+
const sourceStats = readEntryStatSync(sourceUrl, {
|
|
3892
|
+
nullIfNotFound: true,
|
|
3893
|
+
followLink: false,
|
|
3894
|
+
});
|
|
3895
|
+
if (!sourceStats) {
|
|
3896
|
+
if (allowUseless) {
|
|
3897
|
+
return;
|
|
3898
|
+
}
|
|
3899
|
+
throw new Error(`nothing to remove at ${urlToFileSystemPath(sourceUrl)}`);
|
|
3900
|
+
}
|
|
3901
|
+
|
|
3902
|
+
// https://nodejs.org/dist/latest-v13.x/docs/api/fs.html#fs_class_fs_stats
|
|
3903
|
+
// FIFO and socket are ignored, not sure what they are exactly and what to do with them
|
|
3904
|
+
// other libraries ignore them, let's do the same.
|
|
3905
|
+
if (
|
|
3906
|
+
sourceStats.isFile() ||
|
|
3907
|
+
sourceStats.isSymbolicLink() ||
|
|
3908
|
+
sourceStats.isCharacterDevice() ||
|
|
3909
|
+
sourceStats.isBlockDevice()
|
|
3910
|
+
) {
|
|
3911
|
+
removeNonDirectory(
|
|
3912
|
+
sourceUrl.endsWith("/") ? sourceUrl.slice(0, -1) : sourceUrl);
|
|
3913
|
+
} else if (sourceStats.isDirectory()) {
|
|
3914
|
+
const directoryUrl = ensurePathnameTrailingSlash(sourceUrl);
|
|
3915
|
+
removeDirectorySync$1(directoryUrl, {
|
|
3916
|
+
recursive,
|
|
3917
|
+
maxRetries,
|
|
3918
|
+
retryDelay,
|
|
3919
|
+
onlyContent,
|
|
3920
|
+
});
|
|
3921
|
+
}
|
|
3922
|
+
};
|
|
3923
|
+
|
|
3924
|
+
const removeNonDirectory = (sourceUrl) => {
|
|
3925
|
+
const sourcePath = urlToFileSystemPath(sourceUrl);
|
|
3926
|
+
const attempt = () => {
|
|
3927
|
+
unlinkSyncNaive(sourcePath);
|
|
3928
|
+
};
|
|
3929
|
+
attempt();
|
|
3930
|
+
};
|
|
3931
|
+
|
|
3932
|
+
const unlinkSyncNaive = (sourcePath, { handleTemporaryError = null } = {}) => {
|
|
3933
|
+
try {
|
|
3934
|
+
unlinkSync(sourcePath);
|
|
3935
|
+
} catch (error) {
|
|
3936
|
+
if (error.code === "ENOENT") {
|
|
3937
|
+
return;
|
|
3938
|
+
}
|
|
3939
|
+
if (
|
|
3940
|
+
handleTemporaryError &&
|
|
3941
|
+
(error.code === "EBUSY" ||
|
|
3942
|
+
error.code === "EMFILE" ||
|
|
3943
|
+
error.code === "ENFILE" ||
|
|
3944
|
+
error.code === "ENOENT")
|
|
3945
|
+
) {
|
|
3946
|
+
handleTemporaryError(error);
|
|
3947
|
+
return;
|
|
3948
|
+
}
|
|
3949
|
+
throw error;
|
|
3950
|
+
}
|
|
3951
|
+
};
|
|
3952
|
+
|
|
3953
|
+
const removeDirectorySync$1 = (
|
|
3954
|
+
rootDirectoryUrl,
|
|
3955
|
+
{ maxRetries, retryDelay, recursive, onlyContent },
|
|
3956
|
+
) => {
|
|
3957
|
+
const visit = (sourceUrl) => {
|
|
3958
|
+
const sourceStats = readEntryStatSync(sourceUrl, {
|
|
3959
|
+
nullIfNotFound: true,
|
|
3960
|
+
followLink: false,
|
|
3961
|
+
});
|
|
3962
|
+
|
|
3963
|
+
// file/directory not found
|
|
3964
|
+
if (sourceStats === null) {
|
|
3965
|
+
return;
|
|
3966
|
+
}
|
|
3967
|
+
|
|
3968
|
+
if (
|
|
3969
|
+
sourceStats.isFile() ||
|
|
3970
|
+
sourceStats.isCharacterDevice() ||
|
|
3971
|
+
sourceStats.isBlockDevice()
|
|
3972
|
+
) {
|
|
3973
|
+
visitFile(sourceUrl);
|
|
3974
|
+
} else if (sourceStats.isSymbolicLink()) {
|
|
3975
|
+
visitSymbolicLink(sourceUrl);
|
|
3976
|
+
} else if (sourceStats.isDirectory()) {
|
|
3977
|
+
visitDirectory(`${sourceUrl}/`);
|
|
3978
|
+
}
|
|
3979
|
+
};
|
|
3980
|
+
|
|
3981
|
+
const visitDirectory = (directoryUrl) => {
|
|
3982
|
+
const directoryPath = urlToFileSystemPath(directoryUrl);
|
|
3983
|
+
const optionsFromRecursive = recursive
|
|
3984
|
+
? {
|
|
3985
|
+
handleNotEmptyError: () => {
|
|
3986
|
+
removeDirectoryContent(directoryUrl);
|
|
3987
|
+
visitDirectory(directoryUrl);
|
|
3988
|
+
},
|
|
3989
|
+
}
|
|
3990
|
+
: {};
|
|
3991
|
+
removeDirectorySyncNaive(directoryPath, {
|
|
3992
|
+
...optionsFromRecursive,
|
|
3993
|
+
// Workaround for https://github.com/joyent/node/issues/4337
|
|
3994
|
+
...(process.platform === "win32"
|
|
3995
|
+
? {
|
|
3996
|
+
handlePermissionError: (error) => {
|
|
3997
|
+
console.error(
|
|
3998
|
+
`trying to fix windows EPERM after readir on ${directoryPath}`,
|
|
3999
|
+
);
|
|
4000
|
+
|
|
4001
|
+
let openOrCloseError;
|
|
4002
|
+
try {
|
|
4003
|
+
const fd = openSync(directoryPath);
|
|
4004
|
+
closeSync(fd);
|
|
4005
|
+
} catch (e) {
|
|
4006
|
+
openOrCloseError = e;
|
|
4007
|
+
}
|
|
4008
|
+
|
|
4009
|
+
if (openOrCloseError) {
|
|
4010
|
+
if (openOrCloseError.code === "ENOENT") {
|
|
4011
|
+
return;
|
|
4012
|
+
}
|
|
4013
|
+
console.error(
|
|
4014
|
+
`error while trying to fix windows EPERM after readir on ${directoryPath}: ${openOrCloseError.stack}`,
|
|
4015
|
+
);
|
|
4016
|
+
throw error;
|
|
4017
|
+
}
|
|
4018
|
+
removeDirectorySyncNaive(directoryPath, {
|
|
4019
|
+
...optionsFromRecursive,
|
|
4020
|
+
});
|
|
4021
|
+
},
|
|
4022
|
+
}
|
|
4023
|
+
: {}),
|
|
4024
|
+
});
|
|
4025
|
+
};
|
|
4026
|
+
|
|
4027
|
+
const removeDirectoryContent = (directoryUrl) => {
|
|
4028
|
+
const entryNames = readdirSync(new URL(directoryUrl));
|
|
4029
|
+
for (const entryName of entryNames) {
|
|
4030
|
+
const url = resolveUrl$1(entryName, directoryUrl);
|
|
4031
|
+
visit(url);
|
|
4032
|
+
}
|
|
4033
|
+
};
|
|
4034
|
+
|
|
4035
|
+
const visitFile = (fileUrl) => {
|
|
4036
|
+
removeNonDirectory(fileUrl);
|
|
4037
|
+
};
|
|
4038
|
+
|
|
4039
|
+
const visitSymbolicLink = (symbolicLinkUrl) => {
|
|
4040
|
+
removeNonDirectory(symbolicLinkUrl);
|
|
4041
|
+
};
|
|
4042
|
+
|
|
4043
|
+
if (onlyContent) {
|
|
4044
|
+
removeDirectoryContent(rootDirectoryUrl);
|
|
4045
|
+
} else {
|
|
4046
|
+
visitDirectory(rootDirectoryUrl);
|
|
4047
|
+
}
|
|
4048
|
+
};
|
|
4049
|
+
|
|
4050
|
+
const removeDirectorySyncNaive = (
|
|
4051
|
+
directoryPath,
|
|
4052
|
+
{ handleNotEmptyError = null, handlePermissionError = null } = {},
|
|
4053
|
+
) => {
|
|
4054
|
+
try {
|
|
4055
|
+
rmdirSync(directoryPath);
|
|
4056
|
+
} catch (error) {
|
|
4057
|
+
if (handlePermissionError && error.code === "EPERM") {
|
|
4058
|
+
handlePermissionError(error);
|
|
4059
|
+
return;
|
|
4060
|
+
}
|
|
4061
|
+
if (error.code === "ENOENT") {
|
|
4062
|
+
return;
|
|
4063
|
+
}
|
|
4064
|
+
if (
|
|
4065
|
+
handleNotEmptyError &&
|
|
4066
|
+
// linux os
|
|
4067
|
+
(error.code === "ENOTEMPTY" ||
|
|
4068
|
+
// SunOS
|
|
4069
|
+
error.code === "EEXIST")
|
|
4070
|
+
) {
|
|
4071
|
+
handleNotEmptyError(error);
|
|
4072
|
+
return;
|
|
4073
|
+
}
|
|
4074
|
+
throw error;
|
|
4075
|
+
}
|
|
4076
|
+
};
|
|
4077
|
+
|
|
3880
4078
|
process.platform === "win32";
|
|
3881
4079
|
|
|
3882
4080
|
const ensureEmptyDirectory = async (source) => {
|
|
@@ -3906,6 +4104,13 @@ const ensureEmptyDirectory = async (source) => {
|
|
|
3906
4104
|
);
|
|
3907
4105
|
};
|
|
3908
4106
|
|
|
4107
|
+
const removeDirectorySync = (url, options = {}) => {
|
|
4108
|
+
return removeEntrySync(url, {
|
|
4109
|
+
...options,
|
|
4110
|
+
recursive: true,
|
|
4111
|
+
});
|
|
4112
|
+
};
|
|
4113
|
+
|
|
3909
4114
|
const callOnceIdlePerFile = (callback, idleMs) => {
|
|
3910
4115
|
const timeoutIdMap = new Map();
|
|
3911
4116
|
return (fileEvent) => {
|
|
@@ -14163,7 +14368,18 @@ const createUrlInfoTransformer = ({
|
|
|
14163
14368
|
contentIsInlined = false;
|
|
14164
14369
|
}
|
|
14165
14370
|
if (!contentIsInlined) {
|
|
14166
|
-
|
|
14371
|
+
try {
|
|
14372
|
+
writeFileSync(new URL(generatedUrl), urlInfo.content);
|
|
14373
|
+
} catch (e) {
|
|
14374
|
+
if (e.code === "EISDIR") {
|
|
14375
|
+
// happens when directory existed but got delete
|
|
14376
|
+
// we can safely remove that directory and write the new file
|
|
14377
|
+
removeDirectorySync(new URL(generatedUrl));
|
|
14378
|
+
writeFileSync(new URL(generatedUrl), urlInfo.content);
|
|
14379
|
+
} else {
|
|
14380
|
+
throw e;
|
|
14381
|
+
}
|
|
14382
|
+
}
|
|
14167
14383
|
}
|
|
14168
14384
|
const { sourcemapGeneratedUrl, sourcemapReference } = urlInfo;
|
|
14169
14385
|
if (sourcemapGeneratedUrl && sourcemapReference) {
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { writeFileSync } from "@jsenv/filesystem";
|
|
1
|
+
import { removeDirectorySync, writeFileSync } from "@jsenv/filesystem";
|
|
2
2
|
import {
|
|
3
3
|
composeTwoSourcemaps,
|
|
4
4
|
generateSourcemapDataUrl,
|
|
@@ -275,7 +275,18 @@ export const createUrlInfoTransformer = ({
|
|
|
275
275
|
contentIsInlined = false;
|
|
276
276
|
}
|
|
277
277
|
if (!contentIsInlined) {
|
|
278
|
-
|
|
278
|
+
try {
|
|
279
|
+
writeFileSync(new URL(generatedUrl), urlInfo.content);
|
|
280
|
+
} catch (e) {
|
|
281
|
+
if (e.code === "EISDIR") {
|
|
282
|
+
// happens when directory existed but got delete
|
|
283
|
+
// we can safely remove that directory and write the new file
|
|
284
|
+
removeDirectorySync(new URL(generatedUrl));
|
|
285
|
+
writeFileSync(new URL(generatedUrl), urlInfo.content);
|
|
286
|
+
} else {
|
|
287
|
+
throw e;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
279
290
|
}
|
|
280
291
|
const { sourcemapGeneratedUrl, sourcemapReference } = urlInfo;
|
|
281
292
|
if (sourcemapGeneratedUrl && sourcemapReference) {
|