@jsenv/filesystem 2.7.1 → 3.1.0
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/main.js +14 -12
- package/package.json +1 -1
- package/src/assertDirectoryPresence.js +2 -2
- package/src/assertFilePresence.js +2 -2
- package/src/collectDirectoryMatchReport.js +2 -2
- package/src/collectFiles.js +2 -2
- package/src/copyDirectoryContent.js +6 -6
- package/src/{copyFileSystemNode.js → copyEntry.js} +15 -18
- package/src/ensureEmptyDirectory.js +4 -4
- package/src/ensureParentDirectories.js +2 -1
- package/src/fileSystemRootUrl.js +2 -0
- package/src/grantPermissionsOnEntry.js +20 -0
- package/src/internal/{fileSystemNodeToTypeOrNull.js → entryToTypeOrNull.js} +1 -1
- package/src/internal/getCommonPathname.js +0 -1
- package/src/moveDirectoryContent.js +6 -6
- package/src/{moveFileSystemNode.js → moveEntry.js} +10 -10
- package/src/moveUrl.js +10 -0
- package/src/readEntryModificationTime.js +6 -0
- package/src/{readFileSystemNodePermissions.js → readEntryPermissions.js} +1 -1
- package/src/{readFileSystemNodeStat.js → readEntryStat.js} +3 -3
- package/src/readFile.js +8 -7
- package/src/readFileSync.js +20 -0
- package/src/registerDirectoryLifecycle.js +4 -4
- package/src/registerFileLifecycle.js +4 -4
- package/src/{removeFileSystemNode.js → removeEntry.js} +4 -4
- package/src/{testFileSystemNodePermissions.js → testEntryPermissions.js} +3 -2
- package/src/urlToPathname.js +8 -3
- package/src/urlToRelativeUrl.js +0 -1
- package/src/writeDirectory.js +4 -3
- package/src/{writeFileSystemNodeModificationTime.js → writeEntryModificationTime.js} +3 -2
- package/src/{writeFileSystemNodePermissions.js → writeEntryPermissions.js} +3 -2
- package/src/writeFile.js +5 -6
- package/src/writeFileSync.js +20 -0
- package/src/writeSymbolicLink.js +4 -4
- package/src/grantPermissionsOnFileSystemNode.js +0 -20
- package/src/readFileSystemNodeModificationTime.js +0 -6
package/main.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable import/max-dependencies */
|
|
2
|
-
|
|
3
1
|
// we won't internalize @jsenv/url-meta
|
|
4
2
|
// so that @jsenv/url-meta does not becomes nodejs specific
|
|
5
3
|
// but these functions could be inside this repository
|
|
@@ -21,28 +19,31 @@ export { comparePathnames } from "./src/comparePathnames.js"
|
|
|
21
19
|
export { ensureEmptyDirectory } from "./src/ensureEmptyDirectory.js"
|
|
22
20
|
export { ensureParentDirectories } from "./src/ensureParentDirectories.js"
|
|
23
21
|
export { ensureWindowsDriveLetter } from "./src/ensureWindowsDriveLetter.js"
|
|
24
|
-
export {
|
|
22
|
+
export { copyEntry } from "./src/copyEntry.js"
|
|
25
23
|
export { copyDirectoryContent } from "./src/copyDirectoryContent.js"
|
|
26
24
|
export { fileSystemPathToUrl } from "./src/fileSystemPathToUrl.js"
|
|
25
|
+
export { fileSystemRootUrl } from "./src/fileSystemRootUrl.js"
|
|
27
26
|
export { getRealFileSystemUrlSync } from "./src/getRealFileSystemUrlSync.js"
|
|
28
|
-
export {
|
|
27
|
+
export { grantPermissionsOnEntry } from "./src/grantPermissionsOnEntry.js"
|
|
29
28
|
export { isFileSystemPath } from "./src/isFileSystemPath.js"
|
|
30
29
|
export { listFilesMatching } from "./src/listFilesMatching.js"
|
|
31
30
|
export { memoize } from "./src/memoize.js"
|
|
32
31
|
export { moveDirectoryContent } from "./src/moveDirectoryContent.js"
|
|
33
|
-
export {
|
|
32
|
+
export { moveEntry } from "./src/moveEntry.js"
|
|
33
|
+
export { moveUrl } from "./src/moveUrl.js"
|
|
34
34
|
export { readDirectory } from "./src/readDirectory.js"
|
|
35
35
|
export { readFile } from "./src/readFile.js"
|
|
36
|
-
export {
|
|
37
|
-
export {
|
|
38
|
-
export {
|
|
36
|
+
export { readFileSync } from "./src/readFileSync.js"
|
|
37
|
+
export { readEntryModificationTime } from "./src/readEntryModificationTime.js"
|
|
38
|
+
export { readEntryPermissions } from "./src/readEntryPermissions.js"
|
|
39
|
+
export { readEntryStat } from "./src/readEntryStat.js"
|
|
39
40
|
export { readSymbolicLink } from "./src/readSymbolicLink.js"
|
|
40
41
|
export { registerDirectoryLifecycle } from "./src/registerDirectoryLifecycle.js"
|
|
41
42
|
export { registerFileLifecycle } from "./src/registerFileLifecycle.js"
|
|
42
|
-
export {
|
|
43
|
+
export { removeEntry } from "./src/removeEntry.js"
|
|
43
44
|
export { resolveDirectoryUrl } from "./src/resolveDirectoryUrl.js"
|
|
44
45
|
export { resolveUrl } from "./src/resolveUrl.js"
|
|
45
|
-
export {
|
|
46
|
+
export { testEntryPermissions } from "./src/testEntryPermissions.js"
|
|
46
47
|
export { urlIsInsideOf } from "./src/urlIsInsideOf.js"
|
|
47
48
|
export { urlToBasename } from "./src/urlToBasename.js"
|
|
48
49
|
export { urlToExtension } from "./src/urlToExtension.js"
|
|
@@ -56,6 +57,7 @@ export { urlToRessource } from "./src/urlToRessource.js"
|
|
|
56
57
|
export { urlToScheme } from "./src/urlToScheme.js"
|
|
57
58
|
export { writeDirectory } from "./src/writeDirectory.js"
|
|
58
59
|
export { writeFile } from "./src/writeFile.js"
|
|
59
|
-
export {
|
|
60
|
-
export {
|
|
60
|
+
export { writeFileSync } from "./src/writeFileSync.js"
|
|
61
|
+
export { writeEntryModificationTime } from "./src/writeEntryModificationTime.js"
|
|
62
|
+
export { writeEntryPermissions } from "./src/writeEntryPermissions.js"
|
|
61
63
|
export { writeSymbolicLink } from "./src/writeSymbolicLink.js"
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { statsToType } from "./internal/statsToType.js"
|
|
2
2
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
3
3
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
4
|
-
import {
|
|
4
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
5
5
|
|
|
6
6
|
export const assertDirectoryPresence = async (source) => {
|
|
7
7
|
const sourceUrl = assertAndNormalizeFileUrl(source)
|
|
8
8
|
const sourcePath = urlToFileSystemPath(sourceUrl)
|
|
9
9
|
|
|
10
|
-
const sourceStats = await
|
|
10
|
+
const sourceStats = await readEntryStat(sourceUrl, {
|
|
11
11
|
nullIfNotFound: true,
|
|
12
12
|
})
|
|
13
13
|
if (!sourceStats) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { statsToType } from "./internal/statsToType.js"
|
|
2
2
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
3
3
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
4
|
-
import {
|
|
4
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
5
5
|
|
|
6
6
|
export const assertFilePresence = async (source) => {
|
|
7
7
|
const sourceUrl = assertAndNormalizeFileUrl(source)
|
|
8
8
|
const sourcePath = urlToFileSystemPath(sourceUrl)
|
|
9
9
|
|
|
10
|
-
const sourceStats = await
|
|
10
|
+
const sourceStats = await readEntryStat(sourceUrl, {
|
|
11
11
|
nullIfNotFound: true,
|
|
12
12
|
})
|
|
13
13
|
if (!sourceStats) {
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { ensureUrlTrailingSlash } from "./internal/ensureUrlTrailingSlash.js"
|
|
9
9
|
import { assertAndNormalizeDirectoryUrl } from "./assertAndNormalizeDirectoryUrl.js"
|
|
10
10
|
import { readDirectory } from "./readDirectory.js"
|
|
11
|
-
import {
|
|
11
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
12
12
|
import { urlToRelativeUrl } from "./urlToRelativeUrl.js"
|
|
13
13
|
import { comparePathnames } from "./comparePathnames.js"
|
|
14
14
|
|
|
@@ -46,7 +46,7 @@ export const collectDirectoryMatchReport = async ({
|
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
collectOperation.throwIfAborted()
|
|
49
|
-
const directoryChildNodeStats = await
|
|
49
|
+
const directoryChildNodeStats = await readEntryStat(
|
|
50
50
|
directoryChildNodeUrl,
|
|
51
51
|
{
|
|
52
52
|
// we ignore symlink because recursively traversed
|
package/src/collectFiles.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
|
|
8
8
|
import { assertAndNormalizeDirectoryUrl } from "./assertAndNormalizeDirectoryUrl.js"
|
|
9
9
|
import { readDirectory } from "./readDirectory.js"
|
|
10
|
-
import {
|
|
10
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
11
11
|
import { urlToRelativeUrl } from "./urlToRelativeUrl.js"
|
|
12
12
|
import { comparePathnames } from "./comparePathnames.js"
|
|
13
13
|
|
|
@@ -39,7 +39,7 @@ export const collectFiles = async ({
|
|
|
39
39
|
const directoryChildNodeUrl = `${directoryUrl}${directoryItem}`
|
|
40
40
|
|
|
41
41
|
collectOperation.throwIfAborted()
|
|
42
|
-
const directoryChildNodeStats = await
|
|
42
|
+
const directoryChildNodeStats = await readEntryStat(
|
|
43
43
|
directoryChildNodeUrl,
|
|
44
44
|
{
|
|
45
45
|
// we ignore symlink because recursively traversed
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Abort } from "@jsenv/abort"
|
|
2
2
|
|
|
3
3
|
import { assertAndNormalizeDirectoryUrl } from "./assertAndNormalizeDirectoryUrl.js"
|
|
4
|
-
import {
|
|
4
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
5
5
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
6
6
|
import { readSymbolicLink } from "./readSymbolicLink.js"
|
|
7
7
|
import { resolveUrl } from "./resolveUrl.js"
|
|
8
8
|
import { readDirectory } from "./readDirectory.js"
|
|
9
|
-
import {
|
|
9
|
+
import { copyEntry } from "./copyEntry.js"
|
|
10
10
|
import { urlTargetsSameFileSystemPath } from "./internal/urlTargetsSameFileSystemPath.js"
|
|
11
11
|
import { statsToType } from "./internal/statsToType.js"
|
|
12
12
|
|
|
@@ -22,7 +22,7 @@ export const copyDirectoryContent = async ({
|
|
|
22
22
|
let toUrl = assertAndNormalizeDirectoryUrl(to)
|
|
23
23
|
let toPath = urlToFileSystemPath(toUrl)
|
|
24
24
|
|
|
25
|
-
const sourceStats = await
|
|
25
|
+
const sourceStats = await readEntryStat(fromUrl, {
|
|
26
26
|
nullIfNotFound: true,
|
|
27
27
|
followLink: false,
|
|
28
28
|
})
|
|
@@ -36,7 +36,7 @@ export const copyDirectoryContent = async ({
|
|
|
36
36
|
)
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
let destinationStats = await
|
|
39
|
+
let destinationStats = await readEntryStat(toUrl, {
|
|
40
40
|
nullIfNotFound: true,
|
|
41
41
|
// we force false here but in fact we will follow the destination link
|
|
42
42
|
// to know where we will actually move and detect useless move overrite etc..
|
|
@@ -46,7 +46,7 @@ export const copyDirectoryContent = async ({
|
|
|
46
46
|
const linkTarget = await readSymbolicLink(toUrl)
|
|
47
47
|
toUrl = resolveUrl(linkTarget, toUrl)
|
|
48
48
|
toPath = urlToFileSystemPath(toUrl)
|
|
49
|
-
destinationStats = await
|
|
49
|
+
destinationStats = await readEntryStat(toUrl, {
|
|
50
50
|
nullIfNotFound: true,
|
|
51
51
|
})
|
|
52
52
|
}
|
|
@@ -77,7 +77,7 @@ export const copyDirectoryContent = async ({
|
|
|
77
77
|
const from = resolveUrl(directoryEntry, fromUrl)
|
|
78
78
|
const to = resolveUrl(directoryEntry, toUrl)
|
|
79
79
|
await copyOperation.withSignal(async (signal) => {
|
|
80
|
-
await
|
|
80
|
+
await copyEntry({
|
|
81
81
|
signal,
|
|
82
82
|
from,
|
|
83
83
|
to,
|
|
@@ -9,18 +9,18 @@ import { binaryFlagsToPermissions } from "./internal/permissions.js"
|
|
|
9
9
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
10
10
|
import { writeDirectory } from "./writeDirectory.js"
|
|
11
11
|
import { urlToRelativeUrl } from "./urlToRelativeUrl.js"
|
|
12
|
-
import {
|
|
12
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
13
13
|
import { ensureParentDirectories } from "./ensureParentDirectories.js"
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { writeEntryPermissions } from "./writeEntryPermissions.js"
|
|
15
|
+
import { writeEntryModificationTime } from "./writeEntryModificationTime.js"
|
|
16
16
|
import { readDirectory } from "./readDirectory.js"
|
|
17
17
|
import { readSymbolicLink } from "./readSymbolicLink.js"
|
|
18
18
|
import { writeSymbolicLink } from "./writeSymbolicLink.js"
|
|
19
19
|
import { urlIsInsideOf } from "./urlIsInsideOf.js"
|
|
20
|
-
import {
|
|
20
|
+
import { removeEntry } from "./removeEntry.js"
|
|
21
21
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
22
22
|
|
|
23
|
-
export const
|
|
23
|
+
export const copyEntry = async ({
|
|
24
24
|
signal = new AbortController().signal,
|
|
25
25
|
from,
|
|
26
26
|
to,
|
|
@@ -36,7 +36,7 @@ export const copyFileSystemNode = async ({
|
|
|
36
36
|
let toUrl = assertAndNormalizeFileUrl(to)
|
|
37
37
|
let toPath = urlToFileSystemPath(toUrl)
|
|
38
38
|
|
|
39
|
-
const sourceStats = await
|
|
39
|
+
const sourceStats = await readEntryStat(fromUrl, {
|
|
40
40
|
nullIfNotFound: true,
|
|
41
41
|
followLink: false,
|
|
42
42
|
})
|
|
@@ -44,7 +44,7 @@ export const copyFileSystemNode = async ({
|
|
|
44
44
|
throw new Error(`nothing to copy at ${fromPath}`)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
let destinationStats = await
|
|
47
|
+
let destinationStats = await readEntryStat(toUrl, {
|
|
48
48
|
nullIfNotFound: true,
|
|
49
49
|
// we force false here but in fact we will follow the destination link
|
|
50
50
|
// to know where we will actually move and detect useless move overrite etc..
|
|
@@ -55,7 +55,7 @@ export const copyFileSystemNode = async ({
|
|
|
55
55
|
const linkTarget = await readSymbolicLink(toUrl)
|
|
56
56
|
toUrl = resolveUrl(linkTarget, toUrl)
|
|
57
57
|
toPath = urlToFileSystemPath(toUrl)
|
|
58
|
-
destinationStats = await
|
|
58
|
+
destinationStats = await readEntryStat(toUrl, {
|
|
59
59
|
nullIfNotFound: true,
|
|
60
60
|
})
|
|
61
61
|
}
|
|
@@ -130,7 +130,7 @@ export const copyFileSystemNode = async ({
|
|
|
130
130
|
// we must guess ourself the type of the symlink
|
|
131
131
|
// because the destination might not exists because not yet copied
|
|
132
132
|
// https://nodejs.org/dist/latest-v13.x/docs/api/fs.html#fs_fs_symlink_target_path_type_callback
|
|
133
|
-
const targetStats = await
|
|
133
|
+
const targetStats = await readEntryStat(symbolicLinkTargetUrl, {
|
|
134
134
|
nullIfNotFound: true,
|
|
135
135
|
followLink: false,
|
|
136
136
|
})
|
|
@@ -148,13 +148,10 @@ export const copyFileSystemNode = async ({
|
|
|
148
148
|
if (preservePermissions || preserveMtime) {
|
|
149
149
|
const { mode, mtimeMs } = stats
|
|
150
150
|
if (preservePermissions) {
|
|
151
|
-
await
|
|
152
|
-
toUrl,
|
|
153
|
-
binaryFlagsToPermissions(mode),
|
|
154
|
-
)
|
|
151
|
+
await writeEntryPermissions(toUrl, binaryFlagsToPermissions(mode))
|
|
155
152
|
}
|
|
156
153
|
if (preserveMtime) {
|
|
157
|
-
await
|
|
154
|
+
await writeEntryModificationTime(toUrl, mtimeMs)
|
|
158
155
|
}
|
|
159
156
|
}
|
|
160
157
|
}
|
|
@@ -172,11 +169,11 @@ export const copyFileSystemNode = async ({
|
|
|
172
169
|
const names = await readDirectory(directoryUrl)
|
|
173
170
|
await Promise.all(
|
|
174
171
|
names.map(async (name) => {
|
|
175
|
-
const
|
|
176
|
-
const stats = await
|
|
172
|
+
const entryUrl = resolveUrl(name, directoryUrl)
|
|
173
|
+
const stats = await readEntryStat(entryUrl, {
|
|
177
174
|
followLink: false,
|
|
178
175
|
})
|
|
179
|
-
await visit(
|
|
176
|
+
await visit(entryUrl, stats)
|
|
180
177
|
}),
|
|
181
178
|
)
|
|
182
179
|
}
|
|
@@ -198,7 +195,7 @@ export const copyFileSystemNode = async ({
|
|
|
198
195
|
}
|
|
199
196
|
|
|
200
197
|
// remove file, link, directory...
|
|
201
|
-
await
|
|
198
|
+
await removeEntry(toUrl, {
|
|
202
199
|
signal: copyOperation.signal,
|
|
203
200
|
recursive: true,
|
|
204
201
|
allowUseless: true,
|
|
@@ -2,11 +2,11 @@ import { statsToType } from "./internal/statsToType.js"
|
|
|
2
2
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
3
3
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
4
4
|
import { writeDirectory } from "./writeDirectory.js"
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
6
|
+
import { removeEntry } from "./removeEntry.js"
|
|
7
7
|
|
|
8
8
|
export const ensureEmptyDirectory = async (source) => {
|
|
9
|
-
const stats = await
|
|
9
|
+
const stats = await readEntryStat(source, {
|
|
10
10
|
nullIfNotFound: true,
|
|
11
11
|
followLink: false,
|
|
12
12
|
})
|
|
@@ -16,7 +16,7 @@ export const ensureEmptyDirectory = async (source) => {
|
|
|
16
16
|
}
|
|
17
17
|
if (stats.isDirectory()) {
|
|
18
18
|
// if there is a directory remove its content and done
|
|
19
|
-
return
|
|
19
|
+
return removeEntry(source, {
|
|
20
20
|
allowUseless: true,
|
|
21
21
|
recursive: true,
|
|
22
22
|
onlyContent: true,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
2
|
+
import { readEntryPermissions } from "./readEntryPermissions.js"
|
|
3
|
+
import { writeEntryPermissions } from "./writeEntryPermissions.js"
|
|
4
|
+
|
|
5
|
+
export const grantPermissionsOnEntry = async (
|
|
6
|
+
source,
|
|
7
|
+
{ read = false, write = false, execute = false },
|
|
8
|
+
) => {
|
|
9
|
+
const sourceUrl = assertAndNormalizeFileUrl(source)
|
|
10
|
+
|
|
11
|
+
const filePermissions = await readEntryPermissions(sourceUrl)
|
|
12
|
+
await writeEntryPermissions(sourceUrl, {
|
|
13
|
+
owner: { read, write, execute },
|
|
14
|
+
group: { read, write, execute },
|
|
15
|
+
others: { read, write, execute },
|
|
16
|
+
})
|
|
17
|
+
return async () => {
|
|
18
|
+
await writeEntryPermissions(sourceUrl, filePermissions)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -4,7 +4,7 @@ import { urlToFileSystemPath } from "../urlToFileSystemPath.js"
|
|
|
4
4
|
|
|
5
5
|
import { statsToType } from "./statsToType.js"
|
|
6
6
|
|
|
7
|
-
export const
|
|
7
|
+
export const entryToTypeOrNull = (url) => {
|
|
8
8
|
const path = urlToFileSystemPath(url)
|
|
9
9
|
try {
|
|
10
10
|
const stats = statSync(path)
|
|
@@ -10,7 +10,6 @@ export const getCommonPathname = (pathname, otherPathname) => {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const commonString = pathname.slice(0, firstDifferentCharacterIndex + 1)
|
|
13
|
-
|
|
14
13
|
// the first different char is at firstDifferentCharacterIndex
|
|
15
14
|
if (pathname.charAt(firstDifferentCharacterIndex) === "/") {
|
|
16
15
|
return commonString
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Abort } from "@jsenv/abort"
|
|
2
2
|
|
|
3
3
|
import { assertAndNormalizeDirectoryUrl } from "./assertAndNormalizeDirectoryUrl.js"
|
|
4
|
-
import {
|
|
4
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
5
5
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
6
6
|
import { readSymbolicLink } from "./readSymbolicLink.js"
|
|
7
7
|
import { resolveUrl } from "./resolveUrl.js"
|
|
8
8
|
import { readDirectory } from "./readDirectory.js"
|
|
9
|
-
import {
|
|
9
|
+
import { moveEntry } from "./moveEntry.js"
|
|
10
10
|
import { urlTargetsSameFileSystemPath } from "./internal/urlTargetsSameFileSystemPath.js"
|
|
11
11
|
import { statsToType } from "./internal/statsToType.js"
|
|
12
12
|
|
|
@@ -22,7 +22,7 @@ export const moveDirectoryContent = async ({
|
|
|
22
22
|
let toUrl = assertAndNormalizeDirectoryUrl(to)
|
|
23
23
|
let toPath = urlToFileSystemPath(toUrl)
|
|
24
24
|
|
|
25
|
-
const sourceStats = await
|
|
25
|
+
const sourceStats = await readEntryStat(fromUrl, {
|
|
26
26
|
nullIfNotFound: true,
|
|
27
27
|
followLink: false,
|
|
28
28
|
})
|
|
@@ -36,7 +36,7 @@ export const moveDirectoryContent = async ({
|
|
|
36
36
|
)
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
let destinationStats = await
|
|
39
|
+
let destinationStats = await readEntryStat(toUrl, {
|
|
40
40
|
nullIfNotFound: true,
|
|
41
41
|
// we force false here but in fact we will follow the destination link
|
|
42
42
|
// to know where we will actually move and detect useless move overrite etc..
|
|
@@ -46,7 +46,7 @@ export const moveDirectoryContent = async ({
|
|
|
46
46
|
const linkTarget = await readSymbolicLink(toUrl)
|
|
47
47
|
toUrl = resolveUrl(linkTarget, toUrl)
|
|
48
48
|
toPath = urlToFileSystemPath(toUrl)
|
|
49
|
-
destinationStats = await
|
|
49
|
+
destinationStats = await readEntryStat(toUrl, {
|
|
50
50
|
nullIfNotFound: true,
|
|
51
51
|
})
|
|
52
52
|
}
|
|
@@ -78,7 +78,7 @@ export const moveDirectoryContent = async ({
|
|
|
78
78
|
const to = resolveUrl(directoryEntry, toUrl)
|
|
79
79
|
|
|
80
80
|
await moveOperation.withSignal(async (signal) => {
|
|
81
|
-
await
|
|
81
|
+
await moveEntry({
|
|
82
82
|
signal,
|
|
83
83
|
from,
|
|
84
84
|
to,
|
|
@@ -7,12 +7,12 @@ import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
|
7
7
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
8
8
|
import { resolveUrl } from "./resolveUrl.js"
|
|
9
9
|
import { ensureParentDirectories } from "./ensureParentDirectories.js"
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { removeEntry } from "./removeEntry.js"
|
|
11
|
+
import { copyEntry } from "./copyEntry.js"
|
|
12
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
13
13
|
import { readSymbolicLink } from "./readSymbolicLink.js"
|
|
14
14
|
|
|
15
|
-
export const
|
|
15
|
+
export const moveEntry = async ({
|
|
16
16
|
signal = new AbortController().signal,
|
|
17
17
|
from,
|
|
18
18
|
to,
|
|
@@ -25,7 +25,7 @@ export const moveFileSystemNode = async ({
|
|
|
25
25
|
let toUrl = assertAndNormalizeFileUrl(to)
|
|
26
26
|
let toPath = urlToFileSystemPath(toUrl)
|
|
27
27
|
|
|
28
|
-
const sourceStats = await
|
|
28
|
+
const sourceStats = await readEntryStat(fromUrl, {
|
|
29
29
|
nullIfNotFound: true,
|
|
30
30
|
followLink: false,
|
|
31
31
|
})
|
|
@@ -33,7 +33,7 @@ export const moveFileSystemNode = async ({
|
|
|
33
33
|
throw new Error(`nothing to move from ${fromPath}`)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
let destinationStats = await
|
|
36
|
+
let destinationStats = await readEntryStat(toUrl, {
|
|
37
37
|
nullIfNotFound: true,
|
|
38
38
|
// we force false here but in fact we will follow the destination link
|
|
39
39
|
// to know where we will actually move and detect useless move overrite etc..
|
|
@@ -44,7 +44,7 @@ export const moveFileSystemNode = async ({
|
|
|
44
44
|
const linkTarget = await readSymbolicLink(toUrl)
|
|
45
45
|
toUrl = resolveUrl(linkTarget, toUrl)
|
|
46
46
|
toPath = urlToFileSystemPath(toUrl)
|
|
47
|
-
destinationStats = await
|
|
47
|
+
destinationStats = await readEntryStat(toUrl, {
|
|
48
48
|
nullIfNotFound: true,
|
|
49
49
|
})
|
|
50
50
|
}
|
|
@@ -78,7 +78,7 @@ export const moveFileSystemNode = async ({
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// remove file, link, directory...
|
|
81
|
-
await
|
|
81
|
+
await removeEntry(toUrl, {
|
|
82
82
|
signal: moveOperation.signal,
|
|
83
83
|
recursive: true,
|
|
84
84
|
})
|
|
@@ -89,12 +89,12 @@ export const moveFileSystemNode = async ({
|
|
|
89
89
|
moveOperation.throwIfAborted()
|
|
90
90
|
await moveNaive(fromPath, toPath, {
|
|
91
91
|
handleCrossDeviceError: async () => {
|
|
92
|
-
await
|
|
92
|
+
await copyEntry({
|
|
93
93
|
from: fromUrl,
|
|
94
94
|
to: toUrl,
|
|
95
95
|
preserveStat: true,
|
|
96
96
|
})
|
|
97
|
-
await
|
|
97
|
+
await removeEntry(fromUrl, {
|
|
98
98
|
signal: moveOperation.signal,
|
|
99
99
|
recursive: true,
|
|
100
100
|
})
|
package/src/moveUrl.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { urlToRelativeUrl } from "./urlToRelativeUrl.js"
|
|
2
|
+
|
|
3
|
+
export const moveUrl = ({ url, from, to, preferAbsolute = false }) => {
|
|
4
|
+
const relativeUrl = urlToRelativeUrl(url, from)
|
|
5
|
+
const absoluteUrl = new URL(relativeUrl, to).href
|
|
6
|
+
if (preferAbsolute) {
|
|
7
|
+
return absoluteUrl
|
|
8
|
+
}
|
|
9
|
+
return urlToRelativeUrl(absoluteUrl, to)
|
|
10
|
+
}
|
|
@@ -11,7 +11,7 @@ import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
|
11
11
|
|
|
12
12
|
const { stat } = promises
|
|
13
13
|
|
|
14
|
-
export const
|
|
14
|
+
export const readEntryPermissions = async (source) => {
|
|
15
15
|
const sourceUrl = assertAndNormalizeFileUrl(source)
|
|
16
16
|
const sourcePath = urlToFileSystemPath(sourceUrl)
|
|
17
17
|
|
|
@@ -7,11 +7,11 @@ import { lstat, stat } from "node:fs"
|
|
|
7
7
|
|
|
8
8
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
9
9
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
10
|
-
import {
|
|
10
|
+
import { writeEntryPermissions } from "./writeEntryPermissions.js"
|
|
11
11
|
|
|
12
12
|
const isWindows = process.platform === "win32"
|
|
13
13
|
|
|
14
|
-
export const
|
|
14
|
+
export const readEntryStat = async (
|
|
15
15
|
source,
|
|
16
16
|
{ nullIfNotFound = false, followLink = true } = {},
|
|
17
17
|
) => {
|
|
@@ -41,7 +41,7 @@ export const readFileSystemNodeStat = async (
|
|
|
41
41
|
// unfortunately it means we mutate the permissions
|
|
42
42
|
// without being able to restore them to the previous value
|
|
43
43
|
// (because reading current permission would also throw)
|
|
44
|
-
await
|
|
44
|
+
await writeEntryPermissions(sourceUrl, 0o666)
|
|
45
45
|
const stats = await readStat(sourcePath, {
|
|
46
46
|
followLink,
|
|
47
47
|
...handleNotFoundOption,
|
package/src/readFile.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { promisify } from "util"
|
|
2
|
-
import { readFile as readFileNode } from "fs"
|
|
1
|
+
import { promisify } from "node:util"
|
|
2
|
+
import { readFile as readFileNode } from "node:fs"
|
|
3
|
+
|
|
3
4
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
4
|
-
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
5
5
|
|
|
6
6
|
const readFilePromisified = promisify(readFileNode)
|
|
7
|
-
export const readFile = async (value, { as = "
|
|
7
|
+
export const readFile = async (value, { as = "buffer" } = {}) => {
|
|
8
8
|
const fileUrl = assertAndNormalizeFileUrl(value)
|
|
9
|
-
const
|
|
10
|
-
const buffer = await readFilePromisified(filePath)
|
|
9
|
+
const buffer = await readFilePromisified(new URL(fileUrl))
|
|
11
10
|
if (as === "buffer") {
|
|
12
11
|
return buffer
|
|
13
12
|
}
|
|
@@ -17,5 +16,7 @@ export const readFile = async (value, { as = "string" } = {}) => {
|
|
|
17
16
|
if (as === "json") {
|
|
18
17
|
return JSON.parse(buffer.toString())
|
|
19
18
|
}
|
|
20
|
-
throw new Error(
|
|
19
|
+
throw new Error(
|
|
20
|
+
`"as" must be one of "buffer","string","json" received "${as}"`,
|
|
21
|
+
)
|
|
21
22
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { readFileSync as readFileSyncNode } from "node:fs"
|
|
2
|
+
|
|
3
|
+
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
4
|
+
|
|
5
|
+
export const readFileSync = (value, { as = "buffer" } = {}) => {
|
|
6
|
+
const fileUrl = assertAndNormalizeFileUrl(value)
|
|
7
|
+
const buffer = readFileSyncNode(new URL(fileUrl))
|
|
8
|
+
if (as === "buffer") {
|
|
9
|
+
return buffer
|
|
10
|
+
}
|
|
11
|
+
if (as === "string") {
|
|
12
|
+
return buffer.toString()
|
|
13
|
+
}
|
|
14
|
+
if (as === "json") {
|
|
15
|
+
return JSON.parse(buffer.toString())
|
|
16
|
+
}
|
|
17
|
+
throw new Error(
|
|
18
|
+
`"as" must be one of "buffer","string","json" received "${as}"`,
|
|
19
|
+
)
|
|
20
|
+
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
urlToMeta,
|
|
7
7
|
} from "@jsenv/url-meta"
|
|
8
8
|
import { replaceBackSlashesWithSlashes } from "./internal/replaceBackSlashesWithSlashes.js"
|
|
9
|
-
import {
|
|
9
|
+
import { entryToTypeOrNull } from "./internal/entryToTypeOrNull.js"
|
|
10
10
|
import { createWatcher } from "./internal/createWatcher.js"
|
|
11
11
|
import { trackRessources } from "./internal/trackRessources.js"
|
|
12
12
|
import { ensureUrlTrailingSlash } from "./internal/ensureUrlTrailingSlash.js"
|
|
@@ -120,7 +120,7 @@ export const registerDirectoryLifecycle = (
|
|
|
120
120
|
const removedEntryRelativeUrl = relativeUrlCandidateArray.find(
|
|
121
121
|
(relativeUrlCandidate) => {
|
|
122
122
|
const entryUrl = resolveUrl(relativeUrlCandidate, sourceUrl)
|
|
123
|
-
const type =
|
|
123
|
+
const type = entryToTypeOrNull(entryUrl)
|
|
124
124
|
return type === null
|
|
125
125
|
},
|
|
126
126
|
)
|
|
@@ -137,7 +137,7 @@ export const registerDirectoryLifecycle = (
|
|
|
137
137
|
const handleChange = (relativeUrl) => {
|
|
138
138
|
const entryUrl = resolveUrl(relativeUrl, sourceUrl)
|
|
139
139
|
const previousType = contentMap.get(relativeUrl)
|
|
140
|
-
const type =
|
|
140
|
+
const type = entryToTypeOrNull(entryUrl)
|
|
141
141
|
|
|
142
142
|
if (!entryShouldBeWatched({ relativeUrl, type })) {
|
|
143
143
|
return
|
|
@@ -277,7 +277,7 @@ const visitDirectory = ({ directoryUrl, entryFound }) => {
|
|
|
277
277
|
const directoryPath = urlToFileSystemPath(directoryUrl)
|
|
278
278
|
readdirSync(directoryPath).forEach((entry) => {
|
|
279
279
|
const entryUrl = resolveUrl(entry, directoryUrl)
|
|
280
|
-
const type =
|
|
280
|
+
const type = entryToTypeOrNull(entryUrl)
|
|
281
281
|
if (type === null) {
|
|
282
282
|
return
|
|
283
283
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dirname, basename } from "path"
|
|
2
|
-
import {
|
|
2
|
+
import { entryToTypeOrNull } from "./internal/entryToTypeOrNull.js"
|
|
3
3
|
import { createWatcher } from "./internal/createWatcher.js"
|
|
4
4
|
import { trackRessources } from "./internal/trackRessources.js"
|
|
5
5
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
@@ -67,7 +67,7 @@ export const registerFileLifecycle = (
|
|
|
67
67
|
)
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
const sourceType =
|
|
70
|
+
const sourceType = entryToTypeOrNull(sourceUrl)
|
|
71
71
|
if (sourceType === null) {
|
|
72
72
|
if (added) {
|
|
73
73
|
watchFileAdded()
|
|
@@ -102,7 +102,7 @@ const watchFileCreation = (source, callback, keepProcessAlive) => {
|
|
|
102
102
|
directoryWatcher.on("change", (eventType, filename) => {
|
|
103
103
|
if (filename && filename !== sourceFilename) return
|
|
104
104
|
|
|
105
|
-
const type =
|
|
105
|
+
const type = entryToTypeOrNull(source)
|
|
106
106
|
// ignore if something else with that name gets created
|
|
107
107
|
// we are only interested into files
|
|
108
108
|
if (type !== "file") return
|
|
@@ -128,7 +128,7 @@ const watchFileMutation = (
|
|
|
128
128
|
})
|
|
129
129
|
|
|
130
130
|
watcher.on("change", () => {
|
|
131
|
-
const sourceType =
|
|
131
|
+
const sourceType = entryToTypeOrNull(sourceUrl)
|
|
132
132
|
|
|
133
133
|
if (sourceType === null) {
|
|
134
134
|
watcher.close()
|
|
@@ -4,11 +4,11 @@ import { Abort } from "@jsenv/abort"
|
|
|
4
4
|
import { ensureUrlTrailingSlash } from "./internal/ensureUrlTrailingSlash.js"
|
|
5
5
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
6
6
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
7
|
-
import {
|
|
7
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
8
8
|
import { readDirectory } from "./readDirectory.js"
|
|
9
9
|
import { resolveUrl } from "./resolveUrl.js"
|
|
10
10
|
|
|
11
|
-
export const
|
|
11
|
+
export const removeEntry = async (
|
|
12
12
|
source,
|
|
13
13
|
{
|
|
14
14
|
signal = new AbortController().signal,
|
|
@@ -26,7 +26,7 @@ export const removeFileSystemNode = async (
|
|
|
26
26
|
|
|
27
27
|
try {
|
|
28
28
|
removeOperation.throwIfAborted()
|
|
29
|
-
const sourceStats = await
|
|
29
|
+
const sourceStats = await readEntryStat(sourceUrl, {
|
|
30
30
|
nullIfNotFound: true,
|
|
31
31
|
followLink: false,
|
|
32
32
|
})
|
|
@@ -123,7 +123,7 @@ const removeDirectory = async (
|
|
|
123
123
|
|
|
124
124
|
const visit = async (sourceUrl) => {
|
|
125
125
|
removeDirectoryOperation.throwIfAborted()
|
|
126
|
-
const sourceStats = await
|
|
126
|
+
const sourceStats = await readEntryStat(sourceUrl, {
|
|
127
127
|
nullIfNotFound: true,
|
|
128
128
|
followLink: false,
|
|
129
129
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { promises, constants } from "fs"
|
|
1
|
+
import { promises, constants } from "node:fs"
|
|
2
|
+
|
|
2
3
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
3
4
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
4
5
|
|
|
@@ -10,7 +11,7 @@ const {
|
|
|
10
11
|
X_OK,
|
|
11
12
|
} = constants
|
|
12
13
|
|
|
13
|
-
export const
|
|
14
|
+
export const testEntryPermissions = async (
|
|
14
15
|
source,
|
|
15
16
|
{
|
|
16
17
|
read = false,
|
package/src/urlToPathname.js
CHANGED
|
@@ -8,7 +8,12 @@ export const urlToPathname = (url) => {
|
|
|
8
8
|
|
|
9
9
|
const ressourceToPathname = (ressource) => {
|
|
10
10
|
const searchSeparatorIndex = ressource.indexOf("?")
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
if (searchSeparatorIndex > -1) {
|
|
12
|
+
return ressource.slice(0, searchSeparatorIndex)
|
|
13
|
+
}
|
|
14
|
+
const hashIndex = ressource.indexOf("#")
|
|
15
|
+
if (hashIndex > -1) {
|
|
16
|
+
return ressource.slice(0, hashIndex)
|
|
17
|
+
}
|
|
18
|
+
return ressource
|
|
14
19
|
}
|
package/src/urlToRelativeUrl.js
CHANGED
|
@@ -31,7 +31,6 @@ export const urlToRelativeUrl = (url, baseUrl) => {
|
|
|
31
31
|
const urlAsString = String(url)
|
|
32
32
|
return urlAsString
|
|
33
33
|
}
|
|
34
|
-
|
|
35
34
|
const specificPathname = pathname.slice(commonPathname.length)
|
|
36
35
|
const baseSpecificPathname = basePathname.slice(commonPathname.length)
|
|
37
36
|
if (baseSpecificPathname.includes("/")) {
|
package/src/writeDirectory.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { promises } from "fs"
|
|
1
|
+
import { promises } from "node:fs"
|
|
2
|
+
|
|
2
3
|
import { statsToType } from "./internal/statsToType.js"
|
|
3
4
|
import { assertAndNormalizeDirectoryUrl } from "./assertAndNormalizeDirectoryUrl.js"
|
|
4
5
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
5
|
-
import {
|
|
6
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
6
7
|
|
|
7
8
|
// https://nodejs.org/dist/latest-v13.x/docs/api/fs.html#fs_fspromises_mkdir_path_options
|
|
8
9
|
const { mkdir } = promises
|
|
@@ -14,7 +15,7 @@ export const writeDirectory = async (
|
|
|
14
15
|
const destinationUrl = assertAndNormalizeDirectoryUrl(destination)
|
|
15
16
|
const destinationPath = urlToFileSystemPath(destinationUrl)
|
|
16
17
|
|
|
17
|
-
const destinationStats = await
|
|
18
|
+
const destinationStats = await readEntryStat(destinationUrl, {
|
|
18
19
|
nullIfNotFound: true,
|
|
19
20
|
followLink: false,
|
|
20
21
|
})
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { utimes } from "fs"
|
|
1
|
+
import { utimes } from "node:fs"
|
|
2
|
+
|
|
2
3
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
3
4
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
4
5
|
|
|
5
|
-
export const
|
|
6
|
+
export const writeEntryModificationTime = (source, mtime) => {
|
|
6
7
|
const sourceUrl = assertAndNormalizeFileUrl(source)
|
|
7
8
|
const sourcePath = urlToFileSystemPath(sourceUrl)
|
|
8
9
|
const mtimeValue =
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { chmod } from "fs"
|
|
1
|
+
import { chmod } from "node:fs"
|
|
2
|
+
|
|
2
3
|
import { permissionsToBinaryFlags } from "./internal/permissions.js"
|
|
3
4
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
4
5
|
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
5
6
|
|
|
6
|
-
export const
|
|
7
|
+
export const writeEntryPermissions = async (source, permissions) => {
|
|
7
8
|
const sourceUrl = assertAndNormalizeFileUrl(source)
|
|
8
9
|
const sourcePath = urlToFileSystemPath(sourceUrl)
|
|
9
10
|
|
package/src/writeFile.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { promises } from "fs"
|
|
1
|
+
import { promises } from "node:fs"
|
|
2
|
+
|
|
2
3
|
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
3
|
-
import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
4
4
|
import { ensureParentDirectories } from "./ensureParentDirectories.js"
|
|
5
5
|
|
|
6
6
|
// https://nodejs.org/dist/latest-v13.x/docs/api/fs.html#fs_fspromises_writefile_file_data_options
|
|
@@ -8,14 +8,13 @@ const { writeFile: writeFileNode } = promises
|
|
|
8
8
|
|
|
9
9
|
export const writeFile = async (destination, content = "") => {
|
|
10
10
|
const destinationUrl = assertAndNormalizeFileUrl(destination)
|
|
11
|
-
|
|
12
|
-
const destinationPath = urlToFileSystemPath(destinationUrl)
|
|
11
|
+
const destinationUrlObject = new URL(destinationUrl)
|
|
13
12
|
try {
|
|
14
|
-
await writeFileNode(
|
|
13
|
+
await writeFileNode(destinationUrlObject, content)
|
|
15
14
|
} catch (error) {
|
|
16
15
|
if (error.code === "ENOENT") {
|
|
17
16
|
await ensureParentDirectories(destinationUrl)
|
|
18
|
-
await writeFileNode(
|
|
17
|
+
await writeFileNode(destinationUrlObject, content)
|
|
19
18
|
return
|
|
20
19
|
}
|
|
21
20
|
throw error
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { writeFileSync as writeFileSyncNode, mkdirSync } from "node:fs"
|
|
2
|
+
|
|
3
|
+
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
4
|
+
|
|
5
|
+
export const writeFileSync = (destination, content = "") => {
|
|
6
|
+
const destinationUrl = assertAndNormalizeFileUrl(destination)
|
|
7
|
+
const destinationUrlObject = new URL(destinationUrl)
|
|
8
|
+
try {
|
|
9
|
+
writeFileSyncNode(destinationUrlObject, content)
|
|
10
|
+
} catch (error) {
|
|
11
|
+
if (error.code === "ENOENT") {
|
|
12
|
+
mkdirSync(new URL("./", destinationUrlObject), {
|
|
13
|
+
recursive: true,
|
|
14
|
+
})
|
|
15
|
+
writeFileSyncNode(destinationUrlObject, content)
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
throw error
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/writeSymbolicLink.js
CHANGED
|
@@ -6,9 +6,9 @@ import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
|
|
|
6
6
|
import { resolveUrl } from "./resolveUrl.js"
|
|
7
7
|
import { isFileSystemPath } from "./isFileSystemPath.js"
|
|
8
8
|
import { ensureParentDirectories } from "./ensureParentDirectories.js"
|
|
9
|
-
import {
|
|
9
|
+
import { readEntryStat } from "./readEntryStat.js"
|
|
10
10
|
import { readSymbolicLink } from "./readSymbolicLink.js"
|
|
11
|
-
import {
|
|
11
|
+
import { removeEntry } from "./removeEntry.js"
|
|
12
12
|
|
|
13
13
|
// https://nodejs.org/dist/latest-v13.x/docs/api/fs.html#fs_fspromises_symlink_target_path_type
|
|
14
14
|
const { symlink } = promises
|
|
@@ -38,7 +38,7 @@ export const writeSymbolicLink = async ({
|
|
|
38
38
|
// In practice, if code don't specify "type" on windows, you later get EPERM errors
|
|
39
39
|
// when doing operation on the symlink such as "fs.stat"
|
|
40
40
|
if (isWindows && typeof type === "undefined") {
|
|
41
|
-
const toStats = await
|
|
41
|
+
const toStats = await readEntryStat(toInfo.url, {
|
|
42
42
|
nullIfNotFound: true,
|
|
43
43
|
})
|
|
44
44
|
type = toStats && toStats.isDirectory() ? "dir" : "file"
|
|
@@ -60,7 +60,7 @@ export const writeSymbolicLink = async ({
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
if (allowOverwrite) {
|
|
63
|
-
await
|
|
63
|
+
await removeEntry(fromUrl)
|
|
64
64
|
await symlink(toInfo.value, symbolicLinkPath, type)
|
|
65
65
|
return
|
|
66
66
|
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
|
|
2
|
-
import { readFileSystemNodePermissions } from "./readFileSystemNodePermissions.js"
|
|
3
|
-
import { writeFileSystemNodePermissions } from "./writeFileSystemNodePermissions.js"
|
|
4
|
-
|
|
5
|
-
export const grantPermissionsOnFileSystemNode = async (
|
|
6
|
-
source,
|
|
7
|
-
{ read = false, write = false, execute = false },
|
|
8
|
-
) => {
|
|
9
|
-
const sourceUrl = assertAndNormalizeFileUrl(source)
|
|
10
|
-
|
|
11
|
-
const filePermissions = await readFileSystemNodePermissions(sourceUrl)
|
|
12
|
-
await writeFileSystemNodePermissions(sourceUrl, {
|
|
13
|
-
owner: { read, write, execute },
|
|
14
|
-
group: { read, write, execute },
|
|
15
|
-
others: { read, write, execute },
|
|
16
|
-
})
|
|
17
|
-
return async () => {
|
|
18
|
-
await writeFileSystemNodePermissions(sourceUrl, filePermissions)
|
|
19
|
-
}
|
|
20
|
-
}
|