@jsenv/filesystem 2.5.0 → 2.7.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/README.md CHANGED
@@ -18,10 +18,13 @@ console.log(relativeUrl) // "src/file.js"
18
18
  ```js
19
19
  import { listFilesMatching } from "@jsenv/filesystem"
20
20
 
21
- const jsFiles = await listFilesMatching(
22
- "./**/*.js",
23
- new URL("./", import.meta.url),
24
- )
21
+ const jsFiles = await listFilesMatching({
22
+ directoryUrl: new URL("./", import.meta.url),
23
+ patterns: {
24
+ "./**/*.js": true,
25
+ "./**/*.test.js": false,
26
+ },
27
+ })
25
28
  ```
26
29
 
27
30
  ```console
package/main.js CHANGED
@@ -24,6 +24,7 @@ export { ensureWindowsDriveLetter } from "./src/ensureWindowsDriveLetter.js"
24
24
  export { copyFileSystemNode } from "./src/copyFileSystemNode.js"
25
25
  export { copyDirectoryContent } from "./src/copyDirectoryContent.js"
26
26
  export { fileSystemPathToUrl } from "./src/fileSystemPathToUrl.js"
27
+ export { getRealFileSystemUrlSync } from "./src/getRealFileSystemUrlSync.js"
27
28
  export { grantPermissionsOnFileSystemNode } from "./src/grantPermissionsOnFileSystemNode.js"
28
29
  export { isFileSystemPath } from "./src/isFileSystemPath.js"
29
30
  export { listFilesMatching } from "./src/listFilesMatching.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/filesystem",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "description": "Collection of functions to interact with filesystem in Node.js",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -13,7 +13,7 @@
13
13
  "url": "https://github.com/jsenv/filesystem"
14
14
  },
15
15
  "engines": {
16
- "node": ">=14.17.0"
16
+ "node": ">=16.13.0"
17
17
  },
18
18
  "publishConfig": {
19
19
  "access": "public"
@@ -21,48 +21,38 @@
21
21
  "type": "module",
22
22
  "exports": {
23
23
  ".": {
24
- "import": "./main.js",
25
- "require": "./dist/commonjs/jsenv_filesystem.cjs"
24
+ "import": "./main.js"
26
25
  },
27
26
  "./*": "./*"
28
27
  },
28
+ "main": "./main.js",
29
29
  "files": [
30
- "/dist/",
31
30
  "/src/",
32
31
  "/main.js"
33
32
  ],
34
33
  "scripts": {
35
- "eslint-check": "node ./node_modules/eslint/bin/eslint.js .",
36
- "generate-importmap": "node ./script/importmap/generate_importmap.mjs",
37
- "measure-performances": "node ./script/performance/generate_performance_report.mjs --local",
38
- "dist": "npm run build",
39
- "build": "node --experimental-import-meta-resolve ./script/build/build.mjs",
34
+ "eslint": "node ./node_modules/eslint/bin/eslint.js .",
35
+ "importmap": "node ./script/importmap/importmap.mjs",
36
+ "performance": "node --expose-gc ./script/performance/performance.mjs --log",
40
37
  "test": "node ./script/test/test.mjs",
41
38
  "test-with-coverage": "npm run test -- --coverage",
42
- "prettier-format": "node ./script/prettier/prettier_format.mjs",
43
- "prettier-format-stage": "npm run prettier-format -- --staged",
44
- "prettier-check": "npm run prettier-format -- --dry-run",
45
- "prepublishOnly": "node ./script/publish/remove_postinstall.mjs && npm run dist",
46
- "postpublish": "node ./script/publish/restore_postinstall.mjs"
39
+ "prettier": "prettier --write ."
47
40
  },
48
41
  "dependencies": {
49
- "@jsenv/abort": "3.1.1",
50
- "@jsenv/url-meta": "6.0.1"
42
+ "@jsenv/abort": "4.1.2",
43
+ "@jsenv/url-meta": "6.0.3"
51
44
  },
52
45
  "devDependencies": {
53
- "@babel/core": "7.16.0",
54
- "@babel/eslint-parser": "7.16.0",
55
- "@jsenv/assert": "2.3.2",
56
- "@jsenv/core": "23.2.2",
57
- "@jsenv/eslint-config": "16.0.8",
46
+ "@jsenv/assert": "2.4.1",
47
+ "@jsenv/core": "25.2.1",
48
+ "@jsenv/eslint-config": "16.0.9",
58
49
  "@jsenv/github-release-package": "1.2.3",
59
- "@jsenv/importmap-eslint-resolver": "5.1.2",
60
- "@jsenv/importmap-node-module": "2.4.1",
50
+ "@jsenv/importmap-eslint-resolver": "5.2.2",
51
+ "@jsenv/importmap-node-module": "5.1.0",
61
52
  "@jsenv/package-publish": "1.6.2",
62
53
  "@jsenv/performance-impact": "2.2.1",
63
- "@jsenv/prettier-check-project": "5.6.1",
64
- "eslint": "7.32.0",
65
- "eslint-plugin-import": "2.25.2",
66
- "prettier": "2.4.1"
54
+ "eslint": "8.7.0",
55
+ "eslint-plugin-import": "2.25.4",
56
+ "prettier": "2.5.1"
67
57
  }
68
- }
58
+ }
@@ -0,0 +1,48 @@
1
+ import { readdirSync, realpathSync } from "node:fs"
2
+
3
+ import { fileSystemPathToUrl } from "./fileSystemPathToUrl.js"
4
+ import { urlToFileSystemPath } from "./urlToFileSystemPath.js"
5
+
6
+ export const getRealFileSystemUrlSync = (
7
+ fileUrl,
8
+ { followLink = true } = {},
9
+ ) => {
10
+ const pathname = new URL(fileUrl).pathname
11
+ const parts = pathname.slice(1).split("/")
12
+ let reconstructedFileUrl = `file:///`
13
+ if (process.platform === "win32") {
14
+ const windowsDriveLetter = parts.shift()
15
+ reconstructedFileUrl += `${windowsDriveLetter}/`
16
+ }
17
+ let i = 0
18
+ // eslint-disable-next-line no-constant-condition
19
+ while (true) {
20
+ const name = parts[i]
21
+ i++
22
+ const namesOnFileSystem = readdirSync(
23
+ // When Node.js receives "C:/" on windows it returns
24
+ // the process.cwd() directory content...
25
+ // This can be fixed by passing "file:///C:/" directly but as a url object
26
+ new URL(reconstructedFileUrl),
27
+ )
28
+ const foundOnFilesystem = namesOnFileSystem.includes(name)
29
+ if (foundOnFilesystem) {
30
+ reconstructedFileUrl += name
31
+ } else {
32
+ const nameOnFileSystem = namesOnFileSystem.find(
33
+ (nameCandidate) => nameCandidate.toLowerCase() === name.toLowerCase(),
34
+ )
35
+ reconstructedFileUrl += nameOnFileSystem
36
+ }
37
+ if (i === parts.length) {
38
+ if (followLink) {
39
+ const realPath = realpathSync.native(
40
+ urlToFileSystemPath(reconstructedFileUrl),
41
+ )
42
+ return fileSystemPathToUrl(realPath)
43
+ }
44
+ return reconstructedFileUrl
45
+ }
46
+ reconstructedFileUrl += "/"
47
+ }
48
+ }
@@ -1,5 +1,7 @@
1
- import { statSync } from "fs"
1
+ import { statSync } from "node:fs"
2
+
2
3
  import { urlToFileSystemPath } from "../urlToFileSystemPath.js"
4
+
3
5
  import { statsToType } from "./statsToType.js"
4
6
 
5
7
  export const fileSystemNodeToTypeOrNull = (url) => {
@@ -1,33 +1,19 @@
1
1
  import { collectFiles } from "./collectFiles.js"
2
2
 
3
- export const listFilesMatching = async (
4
- patterns,
3
+ export const listFilesMatching = async ({
5
4
  directoryUrl = process.cwd(),
5
+ patterns,
6
6
  signal,
7
- ) => {
8
- if (typeof patterns === "string") {
9
- patterns = [patterns]
10
- } else if (Array.isArray(patterns)) {
11
- throw new TypeError(
12
- `patterns must be a string or an array of strings, got ${patterns}`,
13
- )
7
+ }) => {
8
+ if (typeof patterns !== "object" || patterns === null) {
9
+ throw new TypeError(`patterns must be an object, got ${patterns}`)
14
10
  }
15
11
 
16
- const patternMap = {}
17
- patterns.forEach((pattern, index) => {
18
- if (typeof pattern !== "string") {
19
- throw new TypeError(
20
- `every pattern must be a string, found ${pattern} at index ${index}`,
21
- )
22
- }
23
- patternMap[pattern] = true
24
- })
25
-
26
12
  const fileDatas = await collectFiles({
27
13
  signal,
28
14
  directoryUrl,
29
15
  structuredMetaMap: {
30
- matches: patternMap,
16
+ matches: patterns,
31
17
  },
32
18
  predicate: ({ matches }) => matches,
33
19
  })
@@ -15,9 +15,9 @@ export const readFileSystemNodeStat = async (
15
15
  source,
16
16
  { nullIfNotFound = false, followLink = true } = {},
17
17
  ) => {
18
- if (source.endsWith("/")) source = source.slice(0, -1)
18
+ let sourceUrl = assertAndNormalizeFileUrl(source)
19
+ if (sourceUrl.endsWith("/")) sourceUrl = sourceUrl.slice(0, -1)
19
20
 
20
- const sourceUrl = assertAndNormalizeFileUrl(source)
21
21
  const sourcePath = urlToFileSystemPath(sourceUrl)
22
22
 
23
23
  const handleNotFoundOption = nullIfNotFound
@@ -31,16 +31,18 @@ export const writeSymbolicLink = async ({
31
31
  }) => {
32
32
  const fromUrl = assertAndNormalizeFileUrl(from)
33
33
  const toInfo = getToInfo(to, fromUrl)
34
-
34
+ // Node.js doc at https://nodejs.org/api/fs.html#fssymlinktarget-path-type-callback
35
+ // states the following:
36
+ // "If the type argument is not set, Node.js will autodetect
37
+ // target type and use 'file' or 'dir'"
38
+ // In practice, if code don't specify "type" on windows, you later get EPERM errors
39
+ // when doing operation on the symlink such as "fs.stat"
35
40
  if (isWindows && typeof type === "undefined") {
36
- // without this if you write a symbolic link without specifying the type on windows
37
- // you later get EPERM when doing stat on the symlink
38
41
  const toStats = await readFileSystemNodeStat(toInfo.url, {
39
42
  nullIfNotFound: true,
40
43
  })
41
44
  type = toStats && toStats.isDirectory() ? "dir" : "file"
42
45
  }
43
-
44
46
  const symbolicLinkPath = urlToFileSystemPath(fromUrl)
45
47
  try {
46
48
  await symlink(toInfo.value, symbolicLinkPath, type)