@jsenv/core 39.7.7 → 39.8.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/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,
|
|
6
|
+
import { readdir, chmod, stat, lstat, chmodSync, statSync, lstatSync, promises, unlinkSync, openSync, closeSync, readdirSync, rmdirSync, mkdirSync, readFileSync, writeFileSync as writeFileSync$1, unlink, rmdir, 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";
|
|
@@ -118,17 +118,29 @@ if (
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
function envForceColor() {
|
|
121
|
-
if ('FORCE_COLOR' in env) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
121
|
+
if (!('FORCE_COLOR' in env)) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
125
124
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
if (env.FORCE_COLOR === 'true') {
|
|
126
|
+
return 1;
|
|
127
|
+
}
|
|
129
128
|
|
|
130
|
-
|
|
129
|
+
if (env.FORCE_COLOR === 'false') {
|
|
130
|
+
return 0;
|
|
131
131
|
}
|
|
132
|
+
|
|
133
|
+
if (env.FORCE_COLOR.length === 0) {
|
|
134
|
+
return 1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const level = Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
138
|
+
|
|
139
|
+
if (![0, 1, 2, 3].includes(level)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return level;
|
|
132
144
|
}
|
|
133
145
|
|
|
134
146
|
function translateLevel(level) {
|
|
@@ -199,11 +211,11 @@ function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {
|
|
|
199
211
|
}
|
|
200
212
|
|
|
201
213
|
if ('CI' in env) {
|
|
202
|
-
if ('GITHUB_ACTIONS'
|
|
214
|
+
if (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {
|
|
203
215
|
return 3;
|
|
204
216
|
}
|
|
205
217
|
|
|
206
|
-
if (['TRAVIS', '
|
|
218
|
+
if (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
|
|
207
219
|
return 1;
|
|
208
220
|
}
|
|
209
221
|
|
|
@@ -2058,6 +2070,42 @@ const extractDriveLetter = (resource) => {
|
|
|
2058
2070
|
return null;
|
|
2059
2071
|
};
|
|
2060
2072
|
|
|
2073
|
+
const getParentDirectoryUrl = (url) => {
|
|
2074
|
+
if (url.startsWith("file://")) {
|
|
2075
|
+
// With node.js new URL('../', 'file:///C:/').href
|
|
2076
|
+
// returns "file:///C:/" instead of "file:///"
|
|
2077
|
+
const resource = url.slice("file://".length);
|
|
2078
|
+
const slashLastIndex = resource.lastIndexOf("/");
|
|
2079
|
+
if (slashLastIndex === -1) {
|
|
2080
|
+
return url;
|
|
2081
|
+
}
|
|
2082
|
+
const lastCharIndex = resource.length - 1;
|
|
2083
|
+
if (slashLastIndex === lastCharIndex) {
|
|
2084
|
+
const slashBeforeLastIndex = resource.lastIndexOf(
|
|
2085
|
+
"/",
|
|
2086
|
+
slashLastIndex - 1,
|
|
2087
|
+
);
|
|
2088
|
+
if (slashBeforeLastIndex === -1) {
|
|
2089
|
+
return url;
|
|
2090
|
+
}
|
|
2091
|
+
return `file://${resource.slice(0, slashBeforeLastIndex + 1)}`;
|
|
2092
|
+
}
|
|
2093
|
+
return `file://${resource.slice(0, slashLastIndex + 1)}`;
|
|
2094
|
+
}
|
|
2095
|
+
return new URL(url.endsWith("/") ? "../" : "./", url).href;
|
|
2096
|
+
};
|
|
2097
|
+
|
|
2098
|
+
const findAncestorDirectoryUrl = (url, callback) => {
|
|
2099
|
+
url = String(url);
|
|
2100
|
+
while (url !== "file:///") {
|
|
2101
|
+
if (callback(url)) {
|
|
2102
|
+
return url;
|
|
2103
|
+
}
|
|
2104
|
+
url = getParentDirectoryUrl(url);
|
|
2105
|
+
}
|
|
2106
|
+
return null;
|
|
2107
|
+
};
|
|
2108
|
+
|
|
2061
2109
|
const createCallbackListNotifiedOnce = () => {
|
|
2062
2110
|
let callbacks = [];
|
|
2063
2111
|
let status = "waiting";
|
|
@@ -3610,30 +3658,9 @@ const normalizeMediaType = (value) => {
|
|
|
3610
3658
|
return value;
|
|
3611
3659
|
};
|
|
3612
3660
|
|
|
3613
|
-
const
|
|
3614
|
-
const destinationUrl = assertAndNormalizeFileUrl(destination);
|
|
3615
|
-
const destinationUrlObject = new URL(destinationUrl);
|
|
3616
|
-
if (content && content instanceof URL) {
|
|
3617
|
-
content = readFileSync(content);
|
|
3618
|
-
}
|
|
3619
|
-
try {
|
|
3620
|
-
writeFileSync$1(destinationUrlObject, content);
|
|
3621
|
-
} catch (error) {
|
|
3622
|
-
if (error.code === "ENOENT") {
|
|
3623
|
-
mkdirSync(new URL("./", destinationUrlObject), {
|
|
3624
|
-
recursive: true,
|
|
3625
|
-
});
|
|
3626
|
-
writeFileSync$1(destinationUrlObject, content);
|
|
3627
|
-
return;
|
|
3628
|
-
}
|
|
3629
|
-
throw error;
|
|
3630
|
-
}
|
|
3631
|
-
};
|
|
3632
|
-
|
|
3633
|
-
const removeEntry = async (
|
|
3661
|
+
const removeEntrySync = (
|
|
3634
3662
|
source,
|
|
3635
3663
|
{
|
|
3636
|
-
signal = new AbortController().signal,
|
|
3637
3664
|
allowUseless = false,
|
|
3638
3665
|
recursive = false,
|
|
3639
3666
|
maxRetries = 3,
|
|
@@ -3642,110 +3669,74 @@ const removeEntry = async (
|
|
|
3642
3669
|
} = {},
|
|
3643
3670
|
) => {
|
|
3644
3671
|
const sourceUrl = assertAndNormalizeFileUrl(source);
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
nullIfNotFound: true,
|
|
3653
|
-
followLink: false,
|
|
3654
|
-
});
|
|
3655
|
-
if (!sourceStats) {
|
|
3656
|
-
if (allowUseless) {
|
|
3657
|
-
return;
|
|
3658
|
-
}
|
|
3659
|
-
throw new Error(`nothing to remove at ${urlToFileSystemPath(sourceUrl)}`);
|
|
3672
|
+
const sourceStats = readEntryStatSync(sourceUrl, {
|
|
3673
|
+
nullIfNotFound: true,
|
|
3674
|
+
followLink: false,
|
|
3675
|
+
});
|
|
3676
|
+
if (!sourceStats) {
|
|
3677
|
+
if (allowUseless) {
|
|
3678
|
+
return;
|
|
3660
3679
|
}
|
|
3680
|
+
throw new Error(`nothing to remove at ${urlToFileSystemPath(sourceUrl)}`);
|
|
3681
|
+
}
|
|
3661
3682
|
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
recursive,
|
|
3682
|
-
maxRetries,
|
|
3683
|
-
retryDelay,
|
|
3684
|
-
onlyContent,
|
|
3685
|
-
});
|
|
3686
|
-
}
|
|
3687
|
-
} finally {
|
|
3688
|
-
await removeOperation.end();
|
|
3683
|
+
// https://nodejs.org/dist/latest-v13.x/docs/api/fs.html#fs_class_fs_stats
|
|
3684
|
+
// FIFO and socket are ignored, not sure what they are exactly and what to do with them
|
|
3685
|
+
// other libraries ignore them, let's do the same.
|
|
3686
|
+
if (
|
|
3687
|
+
sourceStats.isFile() ||
|
|
3688
|
+
sourceStats.isSymbolicLink() ||
|
|
3689
|
+
sourceStats.isCharacterDevice() ||
|
|
3690
|
+
sourceStats.isBlockDevice()
|
|
3691
|
+
) {
|
|
3692
|
+
removeNonDirectory$1(
|
|
3693
|
+
sourceUrl.endsWith("/") ? sourceUrl.slice(0, -1) : sourceUrl);
|
|
3694
|
+
} else if (sourceStats.isDirectory()) {
|
|
3695
|
+
const directoryUrl = ensurePathnameTrailingSlash(sourceUrl);
|
|
3696
|
+
removeDirectorySync$1(directoryUrl, {
|
|
3697
|
+
recursive,
|
|
3698
|
+
maxRetries,
|
|
3699
|
+
retryDelay,
|
|
3700
|
+
onlyContent,
|
|
3701
|
+
});
|
|
3689
3702
|
}
|
|
3690
3703
|
};
|
|
3691
3704
|
|
|
3692
|
-
const removeNonDirectory$1 = (sourceUrl
|
|
3705
|
+
const removeNonDirectory$1 = (sourceUrl) => {
|
|
3693
3706
|
const sourcePath = urlToFileSystemPath(sourceUrl);
|
|
3694
|
-
|
|
3695
|
-
let retryCount = 0;
|
|
3696
3707
|
const attempt = () => {
|
|
3697
|
-
|
|
3698
|
-
...(retryCount >= maxRetries
|
|
3699
|
-
? {}
|
|
3700
|
-
: {
|
|
3701
|
-
handleTemporaryError: async () => {
|
|
3702
|
-
retryCount++;
|
|
3703
|
-
return new Promise((resolve) => {
|
|
3704
|
-
setTimeout(() => {
|
|
3705
|
-
resolve(attempt());
|
|
3706
|
-
}, retryCount * retryDelay);
|
|
3707
|
-
});
|
|
3708
|
-
},
|
|
3709
|
-
}),
|
|
3710
|
-
});
|
|
3708
|
+
unlinkSyncNaive(sourcePath);
|
|
3711
3709
|
};
|
|
3712
|
-
|
|
3710
|
+
attempt();
|
|
3713
3711
|
};
|
|
3714
3712
|
|
|
3715
|
-
const
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
)
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
}
|
|
3735
|
-
});
|
|
3736
|
-
});
|
|
3713
|
+
const unlinkSyncNaive = (sourcePath, { handleTemporaryError = null } = {}) => {
|
|
3714
|
+
try {
|
|
3715
|
+
unlinkSync(sourcePath);
|
|
3716
|
+
} catch (error) {
|
|
3717
|
+
if (error.code === "ENOENT") {
|
|
3718
|
+
return;
|
|
3719
|
+
}
|
|
3720
|
+
if (
|
|
3721
|
+
handleTemporaryError &&
|
|
3722
|
+
(error.code === "EBUSY" ||
|
|
3723
|
+
error.code === "EMFILE" ||
|
|
3724
|
+
error.code === "ENFILE" ||
|
|
3725
|
+
error.code === "ENOENT")
|
|
3726
|
+
) {
|
|
3727
|
+
handleTemporaryError(error);
|
|
3728
|
+
return;
|
|
3729
|
+
}
|
|
3730
|
+
throw error;
|
|
3731
|
+
}
|
|
3737
3732
|
};
|
|
3738
3733
|
|
|
3739
|
-
const
|
|
3734
|
+
const removeDirectorySync$1 = (
|
|
3740
3735
|
rootDirectoryUrl,
|
|
3741
|
-
{
|
|
3736
|
+
{ maxRetries, retryDelay, recursive, onlyContent },
|
|
3742
3737
|
) => {
|
|
3743
|
-
const
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
const visit = async (sourceUrl) => {
|
|
3747
|
-
removeDirectoryOperation.throwIfAborted();
|
|
3748
|
-
const sourceStats = await readEntryStat(sourceUrl, {
|
|
3738
|
+
const visit = (sourceUrl) => {
|
|
3739
|
+
const sourceStats = readEntryStatSync(sourceUrl, {
|
|
3749
3740
|
nullIfNotFound: true,
|
|
3750
3741
|
followLink: false,
|
|
3751
3742
|
});
|
|
@@ -3760,31 +3751,30 @@ const removeDirectory = async (
|
|
|
3760
3751
|
sourceStats.isCharacterDevice() ||
|
|
3761
3752
|
sourceStats.isBlockDevice()
|
|
3762
3753
|
) {
|
|
3763
|
-
|
|
3754
|
+
visitFile(sourceUrl);
|
|
3764
3755
|
} else if (sourceStats.isSymbolicLink()) {
|
|
3765
|
-
|
|
3756
|
+
visitSymbolicLink(sourceUrl);
|
|
3766
3757
|
} else if (sourceStats.isDirectory()) {
|
|
3767
|
-
|
|
3758
|
+
visitDirectory(`${sourceUrl}/`);
|
|
3768
3759
|
}
|
|
3769
3760
|
};
|
|
3770
3761
|
|
|
3771
|
-
const visitDirectory =
|
|
3762
|
+
const visitDirectory = (directoryUrl) => {
|
|
3772
3763
|
const directoryPath = urlToFileSystemPath(directoryUrl);
|
|
3773
3764
|
const optionsFromRecursive = recursive
|
|
3774
3765
|
? {
|
|
3775
|
-
handleNotEmptyError:
|
|
3776
|
-
|
|
3777
|
-
|
|
3766
|
+
handleNotEmptyError: () => {
|
|
3767
|
+
removeDirectoryContent(directoryUrl);
|
|
3768
|
+
visitDirectory(directoryUrl);
|
|
3778
3769
|
},
|
|
3779
3770
|
}
|
|
3780
3771
|
: {};
|
|
3781
|
-
|
|
3782
|
-
await removeDirectoryNaive(directoryPath, {
|
|
3772
|
+
removeDirectorySyncNaive(directoryPath, {
|
|
3783
3773
|
...optionsFromRecursive,
|
|
3784
3774
|
// Workaround for https://github.com/joyent/node/issues/4337
|
|
3785
3775
|
...(process.platform === "win32"
|
|
3786
3776
|
? {
|
|
3787
|
-
handlePermissionError:
|
|
3777
|
+
handlePermissionError: (error) => {
|
|
3788
3778
|
console.error(
|
|
3789
3779
|
`trying to fix windows EPERM after readir on ${directoryPath}`,
|
|
3790
3780
|
);
|
|
@@ -3806,8 +3796,7 @@ const removeDirectory = async (
|
|
|
3806
3796
|
);
|
|
3807
3797
|
throw error;
|
|
3808
3798
|
}
|
|
3809
|
-
|
|
3810
|
-
await removeDirectoryNaive(directoryPath, {
|
|
3799
|
+
removeDirectorySyncNaive(directoryPath, {
|
|
3811
3800
|
...optionsFromRecursive,
|
|
3812
3801
|
});
|
|
3813
3802
|
},
|
|
@@ -3816,70 +3805,170 @@ const removeDirectory = async (
|
|
|
3816
3805
|
});
|
|
3817
3806
|
};
|
|
3818
3807
|
|
|
3819
|
-
const removeDirectoryContent =
|
|
3820
|
-
|
|
3821
|
-
const
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
await visit(url);
|
|
3826
|
-
}),
|
|
3827
|
-
);
|
|
3808
|
+
const removeDirectoryContent = (directoryUrl) => {
|
|
3809
|
+
const entryNames = readdirSync(new URL(directoryUrl));
|
|
3810
|
+
for (const entryName of entryNames) {
|
|
3811
|
+
const url = resolveUrl$1(entryName, directoryUrl);
|
|
3812
|
+
visit(url);
|
|
3813
|
+
}
|
|
3828
3814
|
};
|
|
3829
3815
|
|
|
3830
|
-
const visitFile =
|
|
3831
|
-
|
|
3816
|
+
const visitFile = (fileUrl) => {
|
|
3817
|
+
removeNonDirectory$1(fileUrl);
|
|
3832
3818
|
};
|
|
3833
3819
|
|
|
3834
|
-
const visitSymbolicLink =
|
|
3835
|
-
|
|
3820
|
+
const visitSymbolicLink = (symbolicLinkUrl) => {
|
|
3821
|
+
removeNonDirectory$1(symbolicLinkUrl);
|
|
3836
3822
|
};
|
|
3837
3823
|
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
await visitDirectory(rootDirectoryUrl);
|
|
3843
|
-
}
|
|
3844
|
-
} finally {
|
|
3845
|
-
await removeDirectoryOperation.end();
|
|
3824
|
+
if (onlyContent) {
|
|
3825
|
+
removeDirectoryContent(rootDirectoryUrl);
|
|
3826
|
+
} else {
|
|
3827
|
+
visitDirectory(rootDirectoryUrl);
|
|
3846
3828
|
}
|
|
3847
3829
|
};
|
|
3848
3830
|
|
|
3849
|
-
const
|
|
3831
|
+
const removeDirectorySyncNaive = (
|
|
3850
3832
|
directoryPath,
|
|
3851
3833
|
{ handleNotEmptyError = null, handlePermissionError = null } = {},
|
|
3852
3834
|
) => {
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3835
|
+
try {
|
|
3836
|
+
rmdirSync(directoryPath);
|
|
3837
|
+
} catch (error) {
|
|
3838
|
+
if (handlePermissionError && error.code === "EPERM") {
|
|
3839
|
+
handlePermissionError(error);
|
|
3840
|
+
return;
|
|
3841
|
+
}
|
|
3842
|
+
if (error.code === "ENOENT") {
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
if (
|
|
3846
|
+
handleNotEmptyError &&
|
|
3847
|
+
// linux os
|
|
3848
|
+
(error.code === "ENOTEMPTY" ||
|
|
3849
|
+
// SunOS
|
|
3850
|
+
error.code === "EEXIST")
|
|
3851
|
+
) {
|
|
3852
|
+
handleNotEmptyError(error);
|
|
3853
|
+
return;
|
|
3854
|
+
}
|
|
3855
|
+
throw error;
|
|
3856
|
+
}
|
|
3857
|
+
};
|
|
3858
|
+
|
|
3859
|
+
const removeDirectorySync = (url, options = {}) => {
|
|
3860
|
+
return removeEntrySync(url, {
|
|
3861
|
+
...options,
|
|
3862
|
+
recursive: true,
|
|
3863
|
+
});
|
|
3864
|
+
};
|
|
3865
|
+
|
|
3866
|
+
const writeDirectorySync = (
|
|
3867
|
+
destination,
|
|
3868
|
+
{ recursive = true, allowUseless = false, force } = {},
|
|
3869
|
+
) => {
|
|
3870
|
+
const destinationUrl = assertAndNormalizeDirectoryUrl(destination);
|
|
3871
|
+
const destinationPath = urlToFileSystemPath(destinationUrl);
|
|
3872
|
+
|
|
3873
|
+
let destinationStats;
|
|
3874
|
+
try {
|
|
3875
|
+
destinationStats = readEntryStatSync(destinationUrl, {
|
|
3876
|
+
nullIfNotFound: true,
|
|
3877
|
+
followLink: false,
|
|
3878
|
+
});
|
|
3879
|
+
} catch (e) {
|
|
3880
|
+
if (e.code === "ENOTDIR") {
|
|
3881
|
+
let previousNonDirUrl = destinationUrl;
|
|
3882
|
+
// we must try all parent directories as long as it fails with ENOTDIR
|
|
3883
|
+
findAncestorDirectoryUrl(destinationUrl, (ancestorUrl) => {
|
|
3884
|
+
try {
|
|
3885
|
+
statSync(new URL(ancestorUrl));
|
|
3886
|
+
return true;
|
|
3887
|
+
} catch (e) {
|
|
3888
|
+
if (e.code === "ENOTDIR") {
|
|
3889
|
+
previousNonDirUrl = ancestorUrl;
|
|
3890
|
+
return false;
|
|
3891
|
+
}
|
|
3892
|
+
throw e;
|
|
3870
3893
|
}
|
|
3894
|
+
});
|
|
3895
|
+
if (force) {
|
|
3896
|
+
unlinkSync(
|
|
3897
|
+
new URL(
|
|
3898
|
+
previousNonDirUrl
|
|
3899
|
+
// remove trailing slash
|
|
3900
|
+
.slice(0, -1),
|
|
3901
|
+
),
|
|
3902
|
+
);
|
|
3871
3903
|
} else {
|
|
3872
|
-
|
|
3904
|
+
throw new Error(
|
|
3905
|
+
`cannot write directory at ${destinationPath} because there is a file at ${urlToFileSystemPath(
|
|
3906
|
+
previousNonDirUrl,
|
|
3907
|
+
)}`,
|
|
3908
|
+
);
|
|
3873
3909
|
}
|
|
3874
|
-
}
|
|
3875
|
-
|
|
3910
|
+
} else {
|
|
3911
|
+
throw e;
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
|
|
3915
|
+
if (destinationStats) {
|
|
3916
|
+
if (destinationStats.isDirectory()) {
|
|
3917
|
+
if (allowUseless) {
|
|
3918
|
+
return;
|
|
3919
|
+
}
|
|
3920
|
+
throw new Error(`directory already exists at ${destinationPath}`);
|
|
3921
|
+
}
|
|
3922
|
+
const destinationType = statsToType(destinationStats);
|
|
3923
|
+
throw new Error(
|
|
3924
|
+
`cannot write directory at ${destinationPath} because there is a ${destinationType}`,
|
|
3925
|
+
);
|
|
3926
|
+
}
|
|
3927
|
+
|
|
3928
|
+
try {
|
|
3929
|
+
mkdirSync(destinationPath, { recursive });
|
|
3930
|
+
} catch (error) {
|
|
3931
|
+
if (allowUseless && error.code === "EEXIST") {
|
|
3932
|
+
return;
|
|
3933
|
+
}
|
|
3934
|
+
throw error;
|
|
3935
|
+
}
|
|
3876
3936
|
};
|
|
3877
3937
|
|
|
3878
|
-
|
|
3938
|
+
const writeFileSync = (destination, content = "", { force } = {}) => {
|
|
3939
|
+
const destinationUrl = assertAndNormalizeFileUrl(destination);
|
|
3940
|
+
const destinationUrlObject = new URL(destinationUrl);
|
|
3941
|
+
if (content && content instanceof URL) {
|
|
3942
|
+
content = readFileSync(content);
|
|
3943
|
+
}
|
|
3944
|
+
try {
|
|
3945
|
+
writeFileSync$1(destinationUrlObject, content);
|
|
3946
|
+
} catch (error) {
|
|
3947
|
+
if (error.code === "EISDIR") {
|
|
3948
|
+
// happens when directory existed but got deleted and now it's a file
|
|
3949
|
+
if (force) {
|
|
3950
|
+
removeDirectorySync(destinationUrlObject);
|
|
3951
|
+
writeFileSync$1(destinationUrlObject, content);
|
|
3952
|
+
} else {
|
|
3953
|
+
throw error;
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
if (error.code === "ENOENT" || error.code === "ENOTDIR") {
|
|
3957
|
+
writeDirectorySync(new URL("./", destinationUrlObject), {
|
|
3958
|
+
force,
|
|
3959
|
+
recursive: true,
|
|
3960
|
+
});
|
|
3961
|
+
writeFileSync$1(destinationUrlObject, content);
|
|
3962
|
+
return;
|
|
3963
|
+
}
|
|
3964
|
+
throw error;
|
|
3965
|
+
}
|
|
3966
|
+
};
|
|
3879
3967
|
|
|
3880
|
-
const
|
|
3968
|
+
const removeEntry = async (
|
|
3881
3969
|
source,
|
|
3882
3970
|
{
|
|
3971
|
+
signal = new AbortController().signal,
|
|
3883
3972
|
allowUseless = false,
|
|
3884
3973
|
recursive = false,
|
|
3885
3974
|
maxRetries = 3,
|
|
@@ -3888,74 +3977,110 @@ const removeEntrySync = (
|
|
|
3888
3977
|
} = {},
|
|
3889
3978
|
) => {
|
|
3890
3979
|
const sourceUrl = assertAndNormalizeFileUrl(source);
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3980
|
+
|
|
3981
|
+
const removeOperation = Abort.startOperation();
|
|
3982
|
+
removeOperation.addAbortSignal(signal);
|
|
3983
|
+
|
|
3984
|
+
try {
|
|
3985
|
+
removeOperation.throwIfAborted();
|
|
3986
|
+
const sourceStats = await readEntryStat(sourceUrl, {
|
|
3987
|
+
nullIfNotFound: true,
|
|
3988
|
+
followLink: false,
|
|
3989
|
+
});
|
|
3990
|
+
if (!sourceStats) {
|
|
3991
|
+
if (allowUseless) {
|
|
3992
|
+
return;
|
|
3993
|
+
}
|
|
3994
|
+
throw new Error(`nothing to remove at ${urlToFileSystemPath(sourceUrl)}`);
|
|
3898
3995
|
}
|
|
3899
|
-
|
|
3996
|
+
|
|
3997
|
+
// https://nodejs.org/dist/latest-v13.x/docs/api/fs.html#fs_class_fs_stats
|
|
3998
|
+
// FIFO and socket are ignored, not sure what they are exactly and what to do with them
|
|
3999
|
+
// other libraries ignore them, let's do the same.
|
|
4000
|
+
if (
|
|
4001
|
+
sourceStats.isFile() ||
|
|
4002
|
+
sourceStats.isSymbolicLink() ||
|
|
4003
|
+
sourceStats.isCharacterDevice() ||
|
|
4004
|
+
sourceStats.isBlockDevice()
|
|
4005
|
+
) {
|
|
4006
|
+
await removeNonDirectory(
|
|
4007
|
+
sourceUrl.endsWith("/") ? sourceUrl.slice(0, -1) : sourceUrl,
|
|
4008
|
+
{
|
|
4009
|
+
maxRetries,
|
|
4010
|
+
retryDelay,
|
|
4011
|
+
},
|
|
4012
|
+
);
|
|
4013
|
+
} else if (sourceStats.isDirectory()) {
|
|
4014
|
+
await removeDirectory(ensurePathnameTrailingSlash(sourceUrl), {
|
|
4015
|
+
signal: removeOperation.signal,
|
|
4016
|
+
recursive,
|
|
4017
|
+
maxRetries,
|
|
4018
|
+
retryDelay,
|
|
4019
|
+
onlyContent,
|
|
4020
|
+
});
|
|
4021
|
+
}
|
|
4022
|
+
} finally {
|
|
4023
|
+
await removeOperation.end();
|
|
3900
4024
|
}
|
|
4025
|
+
};
|
|
3901
4026
|
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
4027
|
+
const removeNonDirectory = (sourceUrl, { maxRetries, retryDelay }) => {
|
|
4028
|
+
const sourcePath = urlToFileSystemPath(sourceUrl);
|
|
4029
|
+
|
|
4030
|
+
let retryCount = 0;
|
|
4031
|
+
const attempt = () => {
|
|
4032
|
+
return unlinkNaive(sourcePath, {
|
|
4033
|
+
...(retryCount >= maxRetries
|
|
4034
|
+
? {}
|
|
4035
|
+
: {
|
|
4036
|
+
handleTemporaryError: async () => {
|
|
4037
|
+
retryCount++;
|
|
4038
|
+
return new Promise((resolve) => {
|
|
4039
|
+
setTimeout(() => {
|
|
4040
|
+
resolve(attempt());
|
|
4041
|
+
}, retryCount * retryDelay);
|
|
4042
|
+
});
|
|
4043
|
+
},
|
|
4044
|
+
}),
|
|
3920
4045
|
});
|
|
3921
|
-
}
|
|
3922
|
-
};
|
|
3923
|
-
|
|
3924
|
-
const removeNonDirectory = (sourceUrl) => {
|
|
3925
|
-
const sourcePath = urlToFileSystemPath(sourceUrl);
|
|
3926
|
-
const attempt = () => {
|
|
3927
|
-
unlinkSyncNaive(sourcePath);
|
|
3928
4046
|
};
|
|
3929
|
-
attempt();
|
|
4047
|
+
return attempt();
|
|
3930
4048
|
};
|
|
3931
4049
|
|
|
3932
|
-
const
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
4050
|
+
const unlinkNaive = (sourcePath, { handleTemporaryError = null } = {}) => {
|
|
4051
|
+
return new Promise((resolve, reject) => {
|
|
4052
|
+
unlink(sourcePath, (error) => {
|
|
4053
|
+
if (error) {
|
|
4054
|
+
if (error.code === "ENOENT") {
|
|
4055
|
+
resolve();
|
|
4056
|
+
} else if (
|
|
4057
|
+
handleTemporaryError &&
|
|
4058
|
+
(error.code === "EBUSY" ||
|
|
4059
|
+
error.code === "EMFILE" ||
|
|
4060
|
+
error.code === "ENFILE" ||
|
|
4061
|
+
error.code === "ENOENT")
|
|
4062
|
+
) {
|
|
4063
|
+
resolve(handleTemporaryError(error));
|
|
4064
|
+
} else {
|
|
4065
|
+
reject(error);
|
|
4066
|
+
}
|
|
4067
|
+
} else {
|
|
4068
|
+
resolve();
|
|
4069
|
+
}
|
|
4070
|
+
});
|
|
4071
|
+
});
|
|
3951
4072
|
};
|
|
3952
4073
|
|
|
3953
|
-
const
|
|
4074
|
+
const removeDirectory = async (
|
|
3954
4075
|
rootDirectoryUrl,
|
|
3955
|
-
{ maxRetries, retryDelay, recursive, onlyContent },
|
|
4076
|
+
{ signal, maxRetries, retryDelay, recursive, onlyContent },
|
|
3956
4077
|
) => {
|
|
3957
|
-
const
|
|
3958
|
-
|
|
4078
|
+
const removeDirectoryOperation = Abort.startOperation();
|
|
4079
|
+
removeDirectoryOperation.addAbortSignal(signal);
|
|
4080
|
+
|
|
4081
|
+
const visit = async (sourceUrl) => {
|
|
4082
|
+
removeDirectoryOperation.throwIfAborted();
|
|
4083
|
+
const sourceStats = await readEntryStat(sourceUrl, {
|
|
3959
4084
|
nullIfNotFound: true,
|
|
3960
4085
|
followLink: false,
|
|
3961
4086
|
});
|
|
@@ -3970,30 +4095,31 @@ const removeDirectorySync$1 = (
|
|
|
3970
4095
|
sourceStats.isCharacterDevice() ||
|
|
3971
4096
|
sourceStats.isBlockDevice()
|
|
3972
4097
|
) {
|
|
3973
|
-
visitFile(sourceUrl);
|
|
4098
|
+
await visitFile(sourceUrl);
|
|
3974
4099
|
} else if (sourceStats.isSymbolicLink()) {
|
|
3975
|
-
visitSymbolicLink(sourceUrl);
|
|
4100
|
+
await visitSymbolicLink(sourceUrl);
|
|
3976
4101
|
} else if (sourceStats.isDirectory()) {
|
|
3977
|
-
visitDirectory(`${sourceUrl}/`);
|
|
4102
|
+
await visitDirectory(`${sourceUrl}/`);
|
|
3978
4103
|
}
|
|
3979
4104
|
};
|
|
3980
4105
|
|
|
3981
|
-
const visitDirectory = (directoryUrl) => {
|
|
4106
|
+
const visitDirectory = async (directoryUrl) => {
|
|
3982
4107
|
const directoryPath = urlToFileSystemPath(directoryUrl);
|
|
3983
4108
|
const optionsFromRecursive = recursive
|
|
3984
4109
|
? {
|
|
3985
|
-
handleNotEmptyError: () => {
|
|
3986
|
-
removeDirectoryContent(directoryUrl);
|
|
3987
|
-
visitDirectory(directoryUrl);
|
|
4110
|
+
handleNotEmptyError: async () => {
|
|
4111
|
+
await removeDirectoryContent(directoryUrl);
|
|
4112
|
+
await visitDirectory(directoryUrl);
|
|
3988
4113
|
},
|
|
3989
4114
|
}
|
|
3990
4115
|
: {};
|
|
3991
|
-
|
|
4116
|
+
removeDirectoryOperation.throwIfAborted();
|
|
4117
|
+
await removeDirectoryNaive(directoryPath, {
|
|
3992
4118
|
...optionsFromRecursive,
|
|
3993
4119
|
// Workaround for https://github.com/joyent/node/issues/4337
|
|
3994
4120
|
...(process.platform === "win32"
|
|
3995
4121
|
? {
|
|
3996
|
-
handlePermissionError: (error) => {
|
|
4122
|
+
handlePermissionError: async (error) => {
|
|
3997
4123
|
console.error(
|
|
3998
4124
|
`trying to fix windows EPERM after readir on ${directoryPath}`,
|
|
3999
4125
|
);
|
|
@@ -4015,7 +4141,8 @@ const removeDirectorySync$1 = (
|
|
|
4015
4141
|
);
|
|
4016
4142
|
throw error;
|
|
4017
4143
|
}
|
|
4018
|
-
|
|
4144
|
+
|
|
4145
|
+
await removeDirectoryNaive(directoryPath, {
|
|
4019
4146
|
...optionsFromRecursive,
|
|
4020
4147
|
});
|
|
4021
4148
|
},
|
|
@@ -4024,59 +4151,69 @@ const removeDirectorySync$1 = (
|
|
|
4024
4151
|
});
|
|
4025
4152
|
};
|
|
4026
4153
|
|
|
4027
|
-
const removeDirectoryContent = (directoryUrl) => {
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4154
|
+
const removeDirectoryContent = async (directoryUrl) => {
|
|
4155
|
+
removeDirectoryOperation.throwIfAborted();
|
|
4156
|
+
const names = await readDirectory(directoryUrl);
|
|
4157
|
+
await Promise.all(
|
|
4158
|
+
names.map(async (name) => {
|
|
4159
|
+
const url = resolveUrl$1(name, directoryUrl);
|
|
4160
|
+
await visit(url);
|
|
4161
|
+
}),
|
|
4162
|
+
);
|
|
4033
4163
|
};
|
|
4034
4164
|
|
|
4035
|
-
const visitFile = (fileUrl) => {
|
|
4036
|
-
removeNonDirectory(fileUrl);
|
|
4165
|
+
const visitFile = async (fileUrl) => {
|
|
4166
|
+
await removeNonDirectory(fileUrl, { maxRetries, retryDelay });
|
|
4037
4167
|
};
|
|
4038
4168
|
|
|
4039
|
-
const visitSymbolicLink = (symbolicLinkUrl) => {
|
|
4040
|
-
removeNonDirectory(symbolicLinkUrl);
|
|
4169
|
+
const visitSymbolicLink = async (symbolicLinkUrl) => {
|
|
4170
|
+
await removeNonDirectory(symbolicLinkUrl, { maxRetries, retryDelay });
|
|
4041
4171
|
};
|
|
4042
4172
|
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4173
|
+
try {
|
|
4174
|
+
if (onlyContent) {
|
|
4175
|
+
await removeDirectoryContent(rootDirectoryUrl);
|
|
4176
|
+
} else {
|
|
4177
|
+
await visitDirectory(rootDirectoryUrl);
|
|
4178
|
+
}
|
|
4179
|
+
} finally {
|
|
4180
|
+
await removeDirectoryOperation.end();
|
|
4047
4181
|
}
|
|
4048
4182
|
};
|
|
4049
4183
|
|
|
4050
|
-
const
|
|
4184
|
+
const removeDirectoryNaive = (
|
|
4051
4185
|
directoryPath,
|
|
4052
4186
|
{ handleNotEmptyError = null, handlePermissionError = null } = {},
|
|
4053
4187
|
) => {
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4188
|
+
return new Promise((resolve, reject) => {
|
|
4189
|
+
rmdir(directoryPath, (error, lstatObject) => {
|
|
4190
|
+
if (error) {
|
|
4191
|
+
if (handlePermissionError && error.code === "EPERM") {
|
|
4192
|
+
resolve(handlePermissionError(error));
|
|
4193
|
+
} else if (error.code === "ENOENT") {
|
|
4194
|
+
resolve();
|
|
4195
|
+
} else if (
|
|
4196
|
+
handleNotEmptyError &&
|
|
4197
|
+
// linux os
|
|
4198
|
+
(error.code === "ENOTEMPTY" ||
|
|
4199
|
+
// SunOS
|
|
4200
|
+
error.code === "EEXIST")
|
|
4201
|
+
) {
|
|
4202
|
+
resolve(handleNotEmptyError(error));
|
|
4203
|
+
} else {
|
|
4204
|
+
reject(error);
|
|
4205
|
+
}
|
|
4206
|
+
} else {
|
|
4207
|
+
resolve(lstatObject);
|
|
4208
|
+
}
|
|
4209
|
+
});
|
|
4210
|
+
});
|
|
4076
4211
|
};
|
|
4077
4212
|
|
|
4078
4213
|
process.platform === "win32";
|
|
4079
4214
|
|
|
4215
|
+
process.platform === "win32";
|
|
4216
|
+
|
|
4080
4217
|
const ensureEmptyDirectory = async (source) => {
|
|
4081
4218
|
const stats = await readEntryStat(source, {
|
|
4082
4219
|
nullIfNotFound: true,
|
|
@@ -4104,13 +4241,6 @@ const ensureEmptyDirectory = async (source) => {
|
|
|
4104
4241
|
);
|
|
4105
4242
|
};
|
|
4106
4243
|
|
|
4107
|
-
const removeDirectorySync = (url, options = {}) => {
|
|
4108
|
-
return removeEntrySync(url, {
|
|
4109
|
-
...options,
|
|
4110
|
-
recursive: true,
|
|
4111
|
-
});
|
|
4112
|
-
};
|
|
4113
|
-
|
|
4114
4244
|
const callOnceIdlePerFile = (callback, idleMs) => {
|
|
4115
4245
|
const timeoutIdMap = new Map();
|
|
4116
4246
|
return (fileEvent) => {
|
|
@@ -11364,39 +11494,10 @@ const jsenvPluginTranspilation = ({
|
|
|
11364
11494
|
};
|
|
11365
11495
|
|
|
11366
11496
|
const lookupPackageDirectory = (currentUrl) => {
|
|
11367
|
-
|
|
11368
|
-
|
|
11369
|
-
|
|
11370
|
-
|
|
11371
|
-
if (existsSync(new URL(packageJsonFileUrl))) {
|
|
11372
|
-
return currentUrl;
|
|
11373
|
-
}
|
|
11374
|
-
return lookupPackageDirectory(getParentUrl$1(currentUrl));
|
|
11375
|
-
};
|
|
11376
|
-
|
|
11377
|
-
const getParentUrl$1 = (url) => {
|
|
11378
|
-
if (url.startsWith("file://")) {
|
|
11379
|
-
// With node.js new URL('../', 'file:///C:/').href
|
|
11380
|
-
// returns "file:///C:/" instead of "file:///"
|
|
11381
|
-
const resource = url.slice("file://".length);
|
|
11382
|
-
const slashLastIndex = resource.lastIndexOf("/");
|
|
11383
|
-
if (slashLastIndex === -1) {
|
|
11384
|
-
return url;
|
|
11385
|
-
}
|
|
11386
|
-
const lastCharIndex = resource.length - 1;
|
|
11387
|
-
if (slashLastIndex === lastCharIndex) {
|
|
11388
|
-
const slashBeforeLastIndex = resource.lastIndexOf(
|
|
11389
|
-
"/",
|
|
11390
|
-
slashLastIndex - 1,
|
|
11391
|
-
);
|
|
11392
|
-
if (slashBeforeLastIndex === -1) {
|
|
11393
|
-
return url;
|
|
11394
|
-
}
|
|
11395
|
-
return `file://${resource.slice(0, slashBeforeLastIndex + 1)}`;
|
|
11396
|
-
}
|
|
11397
|
-
return `file://${resource.slice(0, slashLastIndex + 1)}`;
|
|
11398
|
-
}
|
|
11399
|
-
return new URL(url.endsWith("/") ? "../" : "./", url).href;
|
|
11497
|
+
return findAncestorDirectoryUrl(currentUrl, (ancestorDirectoryUrl) => {
|
|
11498
|
+
const potentialPackageJsonFileUrl = `${ancestorDirectoryUrl}package.json`;
|
|
11499
|
+
return existsSync(new URL(potentialPackageJsonFileUrl));
|
|
11500
|
+
});
|
|
11400
11501
|
};
|
|
11401
11502
|
|
|
11402
11503
|
const watchSourceFiles = (
|
|
@@ -14368,18 +14469,7 @@ const createUrlInfoTransformer = ({
|
|
|
14368
14469
|
contentIsInlined = false;
|
|
14369
14470
|
}
|
|
14370
14471
|
if (!contentIsInlined) {
|
|
14371
|
-
|
|
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
|
-
}
|
|
14472
|
+
writeFileSync(new URL(generatedUrl), urlInfo.content, { force: true });
|
|
14383
14473
|
}
|
|
14384
14474
|
const { sourcemapGeneratedUrl, sourcemapReference } = urlInfo;
|
|
14385
14475
|
if (sourcemapGeneratedUrl && sourcemapReference) {
|
|
@@ -19175,6 +19265,7 @@ const jsenvPluginProtocolFile = ({
|
|
|
19175
19265
|
if (!urlInfo.url.startsWith("file:")) {
|
|
19176
19266
|
return null;
|
|
19177
19267
|
}
|
|
19268
|
+
const { rootDirectoryUrl } = urlInfo.context;
|
|
19178
19269
|
const generateContent = () => {
|
|
19179
19270
|
const urlObject = new URL(urlInfo.url);
|
|
19180
19271
|
const { firstReference } = urlInfo;
|
|
@@ -19193,11 +19284,12 @@ const jsenvPluginProtocolFile = ({
|
|
|
19193
19284
|
: false;
|
|
19194
19285
|
if (acceptsHtml) {
|
|
19195
19286
|
firstReference.expectedType = "html";
|
|
19196
|
-
const
|
|
19197
|
-
|
|
19198
|
-
|
|
19199
|
-
|
|
19287
|
+
const directoryUrl = urlObject.href;
|
|
19288
|
+
const directoryContentItems = generateDirectoryContentItems(
|
|
19289
|
+
directoryUrl,
|
|
19290
|
+
rootDirectoryUrl,
|
|
19200
19291
|
);
|
|
19292
|
+
const html = generateHtmlForDirectory(directoryContentItems);
|
|
19201
19293
|
return {
|
|
19202
19294
|
type: "html",
|
|
19203
19295
|
contentType: "text/html",
|
|
@@ -19230,32 +19322,13 @@ const jsenvPluginProtocolFile = ({
|
|
|
19230
19322
|
if (e.code !== "ENOENT") {
|
|
19231
19323
|
throw e;
|
|
19232
19324
|
}
|
|
19233
|
-
const
|
|
19234
|
-
|
|
19235
|
-
|
|
19236
|
-
firstExistingAncestorDirectoryUrl = new URL(
|
|
19237
|
-
"../",
|
|
19238
|
-
firstExistingAncestorDirectoryUrl,
|
|
19239
|
-
);
|
|
19240
|
-
if (
|
|
19241
|
-
!urlIsInsideOf(
|
|
19242
|
-
firstExistingAncestorDirectoryUrl,
|
|
19243
|
-
rootDirectoryUrl,
|
|
19244
|
-
)
|
|
19245
|
-
) {
|
|
19246
|
-
firstExistingAncestorDirectoryUrl = rootDirectoryUrl;
|
|
19247
|
-
break;
|
|
19248
|
-
}
|
|
19249
|
-
}
|
|
19250
|
-
|
|
19251
|
-
const firstExistingAncestorDirectoryContent = readdirSync(
|
|
19252
|
-
new URL(firstExistingAncestorDirectoryUrl),
|
|
19325
|
+
const directoryContentItems = generateDirectoryContentItems(
|
|
19326
|
+
urlInfo.url,
|
|
19327
|
+
rootDirectoryUrl,
|
|
19253
19328
|
);
|
|
19254
19329
|
const html = generateHtmlForENOENT(
|
|
19255
19330
|
urlInfo.url,
|
|
19256
|
-
|
|
19257
|
-
firstExistingAncestorDirectoryUrl,
|
|
19258
|
-
urlInfo.context.rootDirectoryUrl,
|
|
19331
|
+
directoryContentItems,
|
|
19259
19332
|
directoryListingUrlMocks,
|
|
19260
19333
|
);
|
|
19261
19334
|
return {
|
|
@@ -19274,11 +19347,9 @@ const jsenvPluginProtocolFile = ({
|
|
|
19274
19347
|
];
|
|
19275
19348
|
};
|
|
19276
19349
|
|
|
19277
|
-
const generateHtmlForDirectory = (
|
|
19278
|
-
directoryUrl
|
|
19279
|
-
|
|
19280
|
-
rootDirectoryUrl,
|
|
19281
|
-
) => {
|
|
19350
|
+
const generateHtmlForDirectory = (directoryContentItems) => {
|
|
19351
|
+
let directoryUrl = directoryContentItems.firstExistingDirectoryUrl;
|
|
19352
|
+
const rootDirectoryUrl = directoryContentItems.rootDirectoryUrl;
|
|
19282
19353
|
directoryUrl = assertAndNormalizeDirectoryUrl(directoryUrl);
|
|
19283
19354
|
|
|
19284
19355
|
const htmlForDirectory = String(readFileSync(htmlFileUrlForDirectory));
|
|
@@ -19287,23 +19358,19 @@ const generateHtmlForDirectory = (
|
|
|
19287
19358
|
directoryUrl,
|
|
19288
19359
|
directoryNav: () =>
|
|
19289
19360
|
generateDirectoryNav(directoryRelativeUrl, rootDirectoryUrl),
|
|
19290
|
-
directoryContent: () =>
|
|
19291
|
-
generateDirectoryContent(
|
|
19292
|
-
directoryContentArray,
|
|
19293
|
-
directoryUrl,
|
|
19294
|
-
rootDirectoryUrl,
|
|
19295
|
-
),
|
|
19361
|
+
directoryContent: () => generateDirectoryContent(directoryContentItems),
|
|
19296
19362
|
};
|
|
19297
19363
|
const html = replacePlaceholders$1(htmlForDirectory, replacers);
|
|
19298
19364
|
return html;
|
|
19299
19365
|
};
|
|
19300
19366
|
const generateHtmlForENOENT = (
|
|
19301
19367
|
url,
|
|
19302
|
-
|
|
19303
|
-
ancestorDirectoryUrl,
|
|
19304
|
-
rootDirectoryUrl,
|
|
19368
|
+
directoryContentItems,
|
|
19305
19369
|
directoryListingUrlMocks,
|
|
19306
19370
|
) => {
|
|
19371
|
+
const ancestorDirectoryUrl = directoryContentItems.firstExistingDirectoryUrl;
|
|
19372
|
+
const rootDirectoryUrl = directoryContentItems.rootDirectoryUrl;
|
|
19373
|
+
|
|
19307
19374
|
const htmlFor404AndAncestorDir = String(
|
|
19308
19375
|
readFileSync(html404AndAncestorDirFileUrl),
|
|
19309
19376
|
);
|
|
@@ -19322,11 +19389,7 @@ const generateHtmlForENOENT = (
|
|
|
19322
19389
|
ancestorDirectoryNav: () =>
|
|
19323
19390
|
generateDirectoryNav(ancestorDirectoryRelativeUrl, rootDirectoryUrl),
|
|
19324
19391
|
ancestorDirectoryContent: () =>
|
|
19325
|
-
generateDirectoryContent(
|
|
19326
|
-
ancestorDirectoryContentArray,
|
|
19327
|
-
ancestorDirectoryUrl,
|
|
19328
|
-
rootDirectoryUrl,
|
|
19329
|
-
),
|
|
19392
|
+
generateDirectoryContent(directoryContentItems),
|
|
19330
19393
|
};
|
|
19331
19394
|
const html = replacePlaceholders$1(htmlFor404AndAncestorDir, replacers);
|
|
19332
19395
|
return html;
|
|
@@ -19368,31 +19431,95 @@ const generateDirectoryNav = (relativeUrl, rootDirectoryUrl) => {
|
|
|
19368
19431
|
}
|
|
19369
19432
|
return dirPartsHtml;
|
|
19370
19433
|
};
|
|
19371
|
-
const
|
|
19372
|
-
|
|
19373
|
-
|
|
19374
|
-
|
|
19375
|
-
)
|
|
19376
|
-
|
|
19377
|
-
|
|
19434
|
+
const generateDirectoryContentItems = (directoryUrl, rootDirectoryUrl) => {
|
|
19435
|
+
let firstExistingDirectoryUrl = new URL("./", directoryUrl);
|
|
19436
|
+
while (!existsSync(firstExistingDirectoryUrl)) {
|
|
19437
|
+
firstExistingDirectoryUrl = new URL("../", firstExistingDirectoryUrl);
|
|
19438
|
+
if (!urlIsInsideOf(firstExistingDirectoryUrl, rootDirectoryUrl)) {
|
|
19439
|
+
firstExistingDirectoryUrl = new URL(rootDirectoryUrl);
|
|
19440
|
+
break;
|
|
19441
|
+
}
|
|
19378
19442
|
}
|
|
19379
|
-
const
|
|
19443
|
+
const directoryContentArray = readdirSync(firstExistingDirectoryUrl);
|
|
19444
|
+
const fileUrls = [];
|
|
19380
19445
|
for (const filename of directoryContentArray) {
|
|
19381
|
-
const fileUrlObject = new URL(filename,
|
|
19382
|
-
|
|
19383
|
-
|
|
19446
|
+
const fileUrlObject = new URL(filename, firstExistingDirectoryUrl);
|
|
19447
|
+
fileUrls.push(fileUrlObject);
|
|
19448
|
+
}
|
|
19449
|
+
package_workspaces: {
|
|
19450
|
+
if (String(firstExistingDirectoryUrl) !== String(rootDirectoryUrl)) {
|
|
19451
|
+
break package_workspaces;
|
|
19452
|
+
}
|
|
19453
|
+
const packageDirectoryUrl = lookupPackageDirectory(rootDirectoryUrl);
|
|
19454
|
+
if (!packageDirectoryUrl) {
|
|
19455
|
+
break package_workspaces;
|
|
19456
|
+
}
|
|
19457
|
+
if (String(packageDirectoryUrl) === String(rootDirectoryUrl)) {
|
|
19458
|
+
break package_workspaces;
|
|
19459
|
+
}
|
|
19460
|
+
let packageContent;
|
|
19461
|
+
try {
|
|
19462
|
+
packageContent = JSON.parse(
|
|
19463
|
+
readFileSync(new URL("package.json", packageDirectoryUrl), "utf8"),
|
|
19464
|
+
);
|
|
19465
|
+
} catch {
|
|
19466
|
+
break package_workspaces;
|
|
19467
|
+
}
|
|
19468
|
+
const { workspaces } = packageContent;
|
|
19469
|
+
if (Array.isArray(workspaces)) {
|
|
19470
|
+
for (const workspace of workspaces) {
|
|
19471
|
+
const workspaceUrlObject = new URL(workspace, packageDirectoryUrl);
|
|
19472
|
+
const workspaceUrl = workspaceUrlObject.href;
|
|
19473
|
+
if (workspaceUrl.endsWith("*")) {
|
|
19474
|
+
const directoryUrl = ensurePathnameTrailingSlash(
|
|
19475
|
+
workspaceUrl.slice(0, -1),
|
|
19476
|
+
);
|
|
19477
|
+
fileUrls.push(new URL(directoryUrl));
|
|
19478
|
+
} else {
|
|
19479
|
+
fileUrls.push(ensurePathnameTrailingSlash(workspaceUrlObject));
|
|
19480
|
+
}
|
|
19481
|
+
}
|
|
19482
|
+
}
|
|
19483
|
+
}
|
|
19484
|
+
|
|
19485
|
+
const sortedUrls = [];
|
|
19486
|
+
for (let fileUrl of fileUrls) {
|
|
19487
|
+
if (lstatSync(fileUrl).isDirectory()) {
|
|
19488
|
+
sortedUrls.push(ensurePathnameTrailingSlash(fileUrl));
|
|
19384
19489
|
} else {
|
|
19385
|
-
|
|
19490
|
+
sortedUrls.push(fileUrl);
|
|
19386
19491
|
}
|
|
19387
19492
|
}
|
|
19388
|
-
|
|
19389
|
-
|
|
19390
|
-
|
|
19391
|
-
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
const
|
|
19493
|
+
sortedUrls.sort((a, b) => {
|
|
19494
|
+
return comparePathnames(a.pathname, b.pathname);
|
|
19495
|
+
});
|
|
19496
|
+
|
|
19497
|
+
const items = [];
|
|
19498
|
+
for (const sortedUrl of sortedUrls) {
|
|
19499
|
+
const fileUrlRelativeToParent = urlToRelativeUrl(
|
|
19500
|
+
sortedUrl,
|
|
19501
|
+
firstExistingDirectoryUrl,
|
|
19502
|
+
);
|
|
19503
|
+
const fileUrlRelativeToRoot = urlToRelativeUrl(sortedUrl, rootDirectoryUrl);
|
|
19395
19504
|
const type = fileUrlRelativeToParent.endsWith("/") ? "dir" : "file";
|
|
19505
|
+
items.push({
|
|
19506
|
+
type,
|
|
19507
|
+
fileUrlRelativeToParent,
|
|
19508
|
+
fileUrlRelativeToRoot,
|
|
19509
|
+
});
|
|
19510
|
+
}
|
|
19511
|
+
items.rootDirectoryUrl = rootDirectoryUrl;
|
|
19512
|
+
items.firstExistingDirectoryUrl = firstExistingDirectoryUrl;
|
|
19513
|
+
return items;
|
|
19514
|
+
};
|
|
19515
|
+
const generateDirectoryContent = (directoryContentItems) => {
|
|
19516
|
+
if (directoryContentItems.length === 0) {
|
|
19517
|
+
return `<p>Directory is empty</p>`;
|
|
19518
|
+
}
|
|
19519
|
+
let html = `<ul class="directory_content">`;
|
|
19520
|
+
for (const directoryContentItem of directoryContentItems) {
|
|
19521
|
+
const { type, fileUrlRelativeToParent, fileUrlRelativeToRoot } =
|
|
19522
|
+
directoryContentItem;
|
|
19396
19523
|
html += `
|
|
19397
19524
|
<li class="directory_child" data-type="${type}">
|
|
19398
19525
|
<a href="/${fileUrlRelativeToRoot}">${fileUrlRelativeToParent}</a>
|