@jsenv/filesystem 2.7.2 → 3.2.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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/main.js +14 -12
  3. package/package.json +3 -4
  4. package/src/assertDirectoryPresence.js +2 -2
  5. package/src/assertFilePresence.js +2 -2
  6. package/src/collectDirectoryMatchReport.js +2 -2
  7. package/src/collectFiles.js +2 -2
  8. package/src/copyDirectoryContent.js +6 -6
  9. package/src/{copyFileSystemNode.js → copyEntry.js} +15 -18
  10. package/src/ensureEmptyDirectory.js +4 -4
  11. package/src/ensureParentDirectories.js +2 -1
  12. package/src/fileSystemRootUrl.js +2 -0
  13. package/src/grantPermissionsOnEntry.js +20 -0
  14. package/src/internal/createWatcher.js +1 -1
  15. package/src/internal/guard_second_call.js +20 -0
  16. package/src/internal/read_entry_info.js +20 -0
  17. package/src/moveDirectoryContent.js +6 -6
  18. package/src/{moveFileSystemNode.js → moveEntry.js} +10 -10
  19. package/src/moveUrl.js +10 -0
  20. package/src/readEntryModificationTime.js +6 -0
  21. package/src/{readFileSystemNodePermissions.js → readEntryPermissions.js} +1 -1
  22. package/src/{readFileSystemNodeStat.js → readEntryStat.js} +3 -3
  23. package/src/readFile.js +8 -7
  24. package/src/readFileSync.js +20 -0
  25. package/src/registerDirectoryLifecycle.js +201 -151
  26. package/src/registerFileLifecycle.js +39 -6
  27. package/src/{removeFileSystemNode.js → removeEntry.js} +4 -4
  28. package/src/{testFileSystemNodePermissions.js → testEntryPermissions.js} +3 -2
  29. package/src/writeDirectory.js +4 -3
  30. package/src/{writeFileSystemNodeModificationTime.js → writeEntryModificationTime.js} +3 -2
  31. package/src/{writeFileSystemNodePermissions.js → writeEntryPermissions.js} +3 -2
  32. package/src/writeFile.js +5 -6
  33. package/src/writeFileSync.js +20 -0
  34. package/src/writeSymbolicLink.js +4 -4
  35. package/src/grantPermissionsOnFileSystemNode.js +0 -20
  36. package/src/internal/fileSystemNodeToTypeOrNull.js +0 -18
  37. package/src/readFileSystemNodeModificationTime.js +0 -6
package/README.md CHANGED
@@ -64,7 +64,7 @@ import { registerDirectoryLifecycle } from "@jsenv/filesystem"
64
64
 
65
65
  const directoryContentDescription = {}
66
66
  const unregister = registerDirectoryLifecycle("file:///directory/", {
67
- watchDescription: {
67
+ watchPatterns: {
68
68
  "./**/*": true,
69
69
  "./node_modules/": false,
70
70
  },
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 { copyFileSystemNode } from "./src/copyFileSystemNode.js"
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 { grantPermissionsOnFileSystemNode } from "./src/grantPermissionsOnFileSystemNode.js"
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 { moveFileSystemNode } from "./src/moveFileSystemNode.js"
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 { readFileSystemNodeModificationTime } from "./src/readFileSystemNodeModificationTime.js"
37
- export { readFileSystemNodePermissions } from "./src/readFileSystemNodePermissions.js"
38
- export { readFileSystemNodeStat } from "./src/readFileSystemNodeStat.js"
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 { removeFileSystemNode } from "./src/removeFileSystemNode.js"
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 { testFileSystemNodePermissions } from "./src/testFileSystemNodePermissions.js"
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 { writeFileSystemNodeModificationTime } from "./src/writeFileSystemNodeModificationTime.js"
60
- export { writeFileSystemNodePermissions } from "./src/writeFileSystemNodePermissions.js"
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/filesystem",
3
- "version": "2.7.2",
3
+ "version": "3.2.0",
4
4
  "description": "Collection of functions to interact with filesystem in Node.js",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -16,8 +16,7 @@
16
16
  "node": ">=16.13.0"
17
17
  },
18
18
  "publishConfig": {
19
- "access": "public",
20
- "registry": "https://registry.npmjs.org"
19
+ "access": "public"
21
20
  },
22
21
  "type": "module",
23
22
  "exports": {
@@ -56,4 +55,4 @@
56
55
  "eslint-plugin-import": "2.25.4",
57
56
  "prettier": "2.5.1"
58
57
  }
59
- }
58
+ }
@@ -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 { readFileSystemNodeStat } from "./readFileSystemNodeStat.js"
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 readFileSystemNodeStat(sourceUrl, {
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 { readFileSystemNodeStat } from "./readFileSystemNodeStat.js"
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 readFileSystemNodeStat(sourceUrl, {
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 { readFileSystemNodeStat } from "./readFileSystemNodeStat.js"
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 readFileSystemNodeStat(
49
+ const directoryChildNodeStats = await readEntryStat(
50
50
  directoryChildNodeUrl,
51
51
  {
52
52
  // we ignore symlink because recursively traversed
@@ -7,7 +7,7 @@ import {
7
7
 
8
8
  import { assertAndNormalizeDirectoryUrl } from "./assertAndNormalizeDirectoryUrl.js"
9
9
  import { readDirectory } from "./readDirectory.js"
10
- import { readFileSystemNodeStat } from "./readFileSystemNodeStat.js"
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 readFileSystemNodeStat(
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 { readFileSystemNodeStat } from "./readFileSystemNodeStat.js"
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 { copyFileSystemNode } from "./copyFileSystemNode.js"
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 readFileSystemNodeStat(fromUrl, {
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 readFileSystemNodeStat(toUrl, {
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 readFileSystemNodeStat(toUrl, {
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 copyFileSystemNode({
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 { readFileSystemNodeStat } from "./readFileSystemNodeStat.js"
12
+ import { readEntryStat } from "./readEntryStat.js"
13
13
  import { ensureParentDirectories } from "./ensureParentDirectories.js"
14
- import { writeFileSystemNodePermissions } from "./writeFileSystemNodePermissions.js"
15
- import { writeFileSystemNodeModificationTime } from "./writeFileSystemNodeModificationTime.js"
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 { removeFileSystemNode } from "./removeFileSystemNode.js"
20
+ import { removeEntry } from "./removeEntry.js"
21
21
  import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
22
22
 
23
- export const copyFileSystemNode = async ({
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 readFileSystemNodeStat(fromUrl, {
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 readFileSystemNodeStat(toUrl, {
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 readFileSystemNodeStat(toUrl, {
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 readFileSystemNodeStat(symbolicLinkTargetUrl, {
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 writeFileSystemNodePermissions(
152
- toUrl,
153
- binaryFlagsToPermissions(mode),
154
- )
151
+ await writeEntryPermissions(toUrl, binaryFlagsToPermissions(mode))
155
152
  }
156
153
  if (preserveMtime) {
157
- await writeFileSystemNodeModificationTime(toUrl, mtimeMs)
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 fileSystemNodeUrl = resolveUrl(name, directoryUrl)
176
- const stats = await readFileSystemNodeStat(fileSystemNodeUrl, {
172
+ const entryUrl = resolveUrl(name, directoryUrl)
173
+ const stats = await readEntryStat(entryUrl, {
177
174
  followLink: false,
178
175
  })
179
- await visit(fileSystemNodeUrl, stats)
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 removeFileSystemNode(toUrl, {
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 { readFileSystemNodeStat } from "./readFileSystemNodeStat.js"
6
- import { removeFileSystemNode } from "./removeFileSystemNode.js"
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 readFileSystemNodeStat(source, {
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 removeFileSystemNode(source, {
19
+ return removeEntry(source, {
20
20
  allowUseless: true,
21
21
  recursive: true,
22
22
  onlyContent: true,
@@ -1,4 +1,5 @@
1
- import { dirname } from "path"
1
+ import { dirname } from "node:path"
2
+
2
3
  import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"
3
4
  import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
4
5
  import { writeDirectory } from "./writeDirectory.js"
@@ -0,0 +1,2 @@
1
+ export const fileSystemRootUrl =
2
+ process.platform === "win32" ? `file:///${process.cwd()[0]}:/` : "file:///"
@@ -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
+ }
@@ -1,4 +1,4 @@
1
- import { watch, openSync, closeSync } from "fs"
1
+ import { watch, openSync, closeSync } from "node:fs"
2
2
 
3
3
  const isWindows = process.platform === "win32"
4
4
 
@@ -0,0 +1,20 @@
1
+ export const guardTooFastSecondCall = (
2
+ callback,
3
+ cooldownBetweenFileEvents = 40,
4
+ ) => {
5
+ const previousCallMsMap = new Map()
6
+ return (fileEvent) => {
7
+ const { relativeUrl } = fileEvent
8
+ const previousCallMs = previousCallMsMap.get(relativeUrl)
9
+ const nowMs = Date.now()
10
+ if (previousCallMs) {
11
+ const msEllapsed = nowMs - previousCallMs
12
+ if (msEllapsed < cooldownBetweenFileEvents) {
13
+ previousCallMsMap.delete(relativeUrl)
14
+ return
15
+ }
16
+ }
17
+ previousCallMsMap.set(relativeUrl, nowMs)
18
+ callback(fileEvent)
19
+ }
20
+ }
@@ -0,0 +1,20 @@
1
+ import { statSync } from "node:fs"
2
+
3
+ import { statsToType } from "./statsToType.js"
4
+
5
+ export const readEntryInfo = (url) => {
6
+ try {
7
+ const stats = statSync(new URL(url))
8
+ const type = statsToType(stats)
9
+ return {
10
+ type,
11
+ atimeMs: stats.atimeMs,
12
+ mtimeMs: stats.mtimeMs,
13
+ }
14
+ } catch (e) {
15
+ if (e.code === "ENOENT") {
16
+ return null
17
+ }
18
+ throw e
19
+ }
20
+ }
@@ -1,12 +1,12 @@
1
1
  import { Abort } from "@jsenv/abort"
2
2
 
3
3
  import { assertAndNormalizeDirectoryUrl } from "./assertAndNormalizeDirectoryUrl.js"
4
- import { readFileSystemNodeStat } from "./readFileSystemNodeStat.js"
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 { moveFileSystemNode } from "./moveFileSystemNode.js"
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 readFileSystemNodeStat(fromUrl, {
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 readFileSystemNodeStat(toUrl, {
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 readFileSystemNodeStat(toUrl, {
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 moveFileSystemNode({
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 { removeFileSystemNode } from "./removeFileSystemNode.js"
11
- import { copyFileSystemNode } from "./copyFileSystemNode.js"
12
- import { readFileSystemNodeStat } from "./readFileSystemNodeStat.js"
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 moveFileSystemNode = async ({
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 readFileSystemNodeStat(fromUrl, {
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 readFileSystemNodeStat(toUrl, {
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 readFileSystemNodeStat(toUrl, {
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 removeFileSystemNode(toUrl, {
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 copyFileSystemNode({
92
+ await copyEntry({
93
93
  from: fromUrl,
94
94
  to: toUrl,
95
95
  preserveStat: true,
96
96
  })
97
- await removeFileSystemNode(fromUrl, {
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
+ }
@@ -0,0 +1,6 @@
1
+ import { readEntryStat } from "./readEntryStat.js"
2
+
3
+ export const readEntryModificationTime = async (source) => {
4
+ const stats = await readEntryStat(source)
5
+ return Math.floor(stats.mtimeMs)
6
+ }
@@ -11,7 +11,7 @@ import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
11
11
 
12
12
  const { stat } = promises
13
13
 
14
- export const readFileSystemNodePermissions = async (source) => {
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 { writeFileSystemNodePermissions } from "./writeFileSystemNodePermissions.js"
10
+ import { writeEntryPermissions } from "./writeEntryPermissions.js"
11
11
 
12
12
  const isWindows = process.platform === "win32"
13
13
 
14
- export const readFileSystemNodeStat = async (
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 writeFileSystemNodePermissions(sourceUrl, 0o666)
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 = "string" } = {}) => {
7
+ export const readFile = async (value, { as = "buffer" } = {}) => {
8
8
  const fileUrl = assertAndNormalizeFileUrl(value)
9
- const filePath = urlToFileSystemPath(fileUrl)
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(`as must be one of buffer,string,json, received ${as}.`)
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
+ }