@magic/fs 0.0.30 → 0.0.32
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 +14 -4
- package/package.json +16 -10
- package/src/{exists.mjs → exists.js} +5 -3
- package/src/{fs.mjs → fs.js} +4 -4
- package/src/{getContentType.mjs → getContentType.js} +13 -5
- package/src/getDirectories.js +144 -0
- package/src/{getFilePath.mjs → getFilePath.js} +18 -3
- package/src/{getFileType.mjs → getFileType.js} +6 -1
- package/src/getFiles.js +134 -0
- package/src/index.js +24 -0
- package/src/{mkdirp.mjs → mkdirp.js} +9 -3
- package/src/{rmrf.mjs → rmrf.js} +18 -3
- package/types/exists.d.ts +2 -0
- package/types/fs.d.ts +109 -0
- package/types/getContentType.d.ts +1 -0
- package/types/getDirectories.d.ts +11 -0
- package/types/getFilePath.d.ts +9 -0
- package/types/getFileType.d.ts +1 -0
- package/types/getFiles.d.ts +9 -0
- package/types/index.d.ts +124 -0
- package/types/mkdirp.d.ts +1 -0
- package/types/rmrf.d.ts +4 -0
- package/src/contentTypes.mjs +0 -3
- package/src/getDirectories.mjs +0 -137
- package/src/getFiles.mjs +0 -107
- package/src/index.mjs +0 -24
package/README.md
CHANGED
|
@@ -72,9 +72,9 @@ rmDir
|
|
|
72
72
|
### export overloads:
|
|
73
73
|
|
|
74
74
|
```javascript
|
|
75
|
-
rmdir, rmDir
|
|
76
|
-
readfile, readFile
|
|
77
|
-
readdir, readDir
|
|
75
|
+
// rmdir, rmDir
|
|
76
|
+
// readfile, readFile
|
|
77
|
+
// readdir, readDir
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
### Additional functions:
|
|
@@ -307,7 +307,17 @@ update dependencies
|
|
|
307
307
|
- remove deprecated getFiles and getDirectories api
|
|
308
308
|
- add minDepth option
|
|
309
309
|
|
|
310
|
-
##### 0.0.31
|
|
310
|
+
##### 0.0.31
|
|
311
|
+
|
|
312
|
+
- add tests for [...threedot_dirs]
|
|
313
|
+
- update dependencies
|
|
314
|
+
|
|
315
|
+
##### 0.0.32
|
|
316
|
+
|
|
317
|
+
- add jsdoc types
|
|
318
|
+
- update dependencies
|
|
319
|
+
|
|
320
|
+
##### 0.0.33 - unreleased
|
|
311
321
|
|
|
312
322
|
...
|
|
313
323
|
|
package/package.json
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magic/fs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"author": "Wizards & Witches",
|
|
5
5
|
"description": "nodejs fs promises + goodies",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
7
7
|
"homepage": "https://magic.github.io/fs",
|
|
8
8
|
"main": "src/index.mjs",
|
|
9
|
+
"types": "types/index.d.ts",
|
|
9
10
|
"module": "src/index.mjs",
|
|
10
11
|
"type": "module",
|
|
11
12
|
"scripts": {
|
|
12
13
|
"start": "npm test",
|
|
14
|
+
"build": "tsc && npm run format",
|
|
15
|
+
"prepublishOnly": "npm run test && npm run build",
|
|
13
16
|
"test": "t --exclude docs example config.js",
|
|
14
17
|
"format": "f -w --exclude docs",
|
|
15
18
|
"format:check": "f",
|
|
16
19
|
"calls": "calls",
|
|
17
|
-
"build": "NODE_ENV=production magic build",
|
|
20
|
+
"build:docs": "NODE_ENV=production magic build",
|
|
18
21
|
"prod": "NODE_ENV=production magic build serve",
|
|
19
22
|
"clean": "magic clean",
|
|
20
23
|
"serve": "magic serve",
|
|
@@ -38,18 +41,21 @@
|
|
|
38
41
|
"@magic-modules/pre": "0.0.12",
|
|
39
42
|
"@magic-themes/docs": "0.0.15",
|
|
40
43
|
"@magic/core": "0.0.156",
|
|
41
|
-
"@magic/format": "0.0.
|
|
42
|
-
"@magic/test": "0.2.
|
|
44
|
+
"@magic/format": "0.0.68",
|
|
45
|
+
"@magic/test": "0.2.22",
|
|
46
|
+
"@types/node": "24.7.2",
|
|
47
|
+
"typescript": "5.9.3"
|
|
43
48
|
},
|
|
44
49
|
"dependencies": {
|
|
45
|
-
"@magic/deep": "0.1.
|
|
46
|
-
"@magic/error": "0.0.
|
|
47
|
-
"@magic/log": "0.1.
|
|
48
|
-
"@magic/mime-types": "0.0.
|
|
49
|
-
"@magic/types": "0.1.
|
|
50
|
+
"@magic/deep": "0.1.18",
|
|
51
|
+
"@magic/error": "0.0.20",
|
|
52
|
+
"@magic/log": "0.1.20",
|
|
53
|
+
"@magic/mime-types": "0.0.21",
|
|
54
|
+
"@magic/types": "0.1.29"
|
|
50
55
|
},
|
|
51
56
|
"files": [
|
|
52
|
-
"src"
|
|
57
|
+
"src",
|
|
58
|
+
"types"
|
|
53
59
|
],
|
|
54
60
|
"contributors": [
|
|
55
61
|
{
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { fs } from './fs.
|
|
1
|
+
import { fs } from './fs.js'
|
|
2
2
|
|
|
3
3
|
import error from '@magic/error'
|
|
4
4
|
import is from '@magic/types'
|
|
5
5
|
|
|
6
6
|
const libName = '@magic/fs.exists'
|
|
7
7
|
|
|
8
|
+
/** @type {(f: import('node:fs').PathLike) => Promise<boolean>} */
|
|
8
9
|
export const exists = async f => {
|
|
9
10
|
if (is.empty(f)) {
|
|
10
11
|
throw error(`${libName} expects argument to be non-empty`, 'E_ARG_EMPTY')
|
|
@@ -18,10 +19,11 @@ export const exists = async f => {
|
|
|
18
19
|
await fs.stat(f)
|
|
19
20
|
return true
|
|
20
21
|
} catch (e) {
|
|
21
|
-
|
|
22
|
+
const err = /** @type {Error & { code: string }} */ (e)
|
|
23
|
+
if (err.code === 'ENOENT') {
|
|
22
24
|
return false
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
throw error(
|
|
27
|
+
throw error(err.message, err.code || err.name)
|
|
26
28
|
}
|
|
27
29
|
}
|
package/src/{fs.mjs → fs.js}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import fso from 'fs'
|
|
2
|
-
import util from 'util'
|
|
1
|
+
import fso from 'node:fs'
|
|
2
|
+
import util from 'node:util'
|
|
3
3
|
|
|
4
4
|
const readDir = fso.promises.readdir
|
|
5
5
|
const readFile = fso.promises.readFile
|
|
6
6
|
const rmdir = fso.promises.rmdir
|
|
7
7
|
|
|
8
|
-
export const fs = {
|
|
8
|
+
export const fs = /** @type {const} */ ({
|
|
9
9
|
...fso,
|
|
10
10
|
...fso.promises,
|
|
11
11
|
exists: util.promisify(fso.exists),
|
|
@@ -16,4 +16,4 @@ export const fs = {
|
|
|
16
16
|
rmdir,
|
|
17
17
|
rmDir: rmdir,
|
|
18
18
|
watch: fso.watch,
|
|
19
|
-
}
|
|
19
|
+
})
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { contentTypes } from './contentTypes.mjs'
|
|
3
|
-
|
|
1
|
+
import mimes from '@magic/mime-types'
|
|
4
2
|
import is from '@magic/types'
|
|
5
3
|
import error from '@magic/error'
|
|
6
4
|
|
|
5
|
+
import { getFileType } from './getFileType.js'
|
|
6
|
+
|
|
7
7
|
const libName = '@magic/fs.getContentType'
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {string} uri
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
9
14
|
export const getContentType = uri => {
|
|
10
15
|
if (is.empty(uri)) {
|
|
11
16
|
throw error(`${libName}: need uri to be a non-empty string`, 'E_ARG_EMPTY')
|
|
@@ -17,8 +22,11 @@ export const getContentType = uri => {
|
|
|
17
22
|
|
|
18
23
|
const fileType = getFileType(uri)
|
|
19
24
|
let contentType = 'text/plain'
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
|
|
26
|
+
const mimeTypes = /** @type {Record<string, string>} */ (mimes)
|
|
27
|
+
|
|
28
|
+
if (fileType in mimeTypes) {
|
|
29
|
+
contentType = mimeTypes[fileType]
|
|
22
30
|
}
|
|
23
31
|
|
|
24
32
|
return contentType
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
|
|
3
|
+
import is from '@magic/types'
|
|
4
|
+
import deep from '@magic/deep'
|
|
5
|
+
import error from '@magic/error'
|
|
6
|
+
|
|
7
|
+
import { fs } from './fs.js'
|
|
8
|
+
|
|
9
|
+
import { getFilePath } from './getFilePath.js'
|
|
10
|
+
|
|
11
|
+
const libName = '@magic/fs.getDirectories'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {object} Options
|
|
15
|
+
* @property {string} [root]
|
|
16
|
+
* @property {number} [maxDepth]
|
|
17
|
+
* @property {number} [minDepth]
|
|
18
|
+
* @property {boolean | number} [depth]
|
|
19
|
+
* @property {boolean} [noRoot]
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string | string[]} dir
|
|
24
|
+
* @param {number | false | Options} [options]
|
|
25
|
+
* if options is a number, its the max depth of recursion.
|
|
26
|
+
* if it is false, maxDepth is set to 1
|
|
27
|
+
* @returns {Promise<string[]>}
|
|
28
|
+
*/
|
|
29
|
+
export const getDirectories = async (dir, options = {}) => {
|
|
30
|
+
if (is.number(options)) {
|
|
31
|
+
options = {
|
|
32
|
+
maxDepth: options,
|
|
33
|
+
}
|
|
34
|
+
} else if (options === false) {
|
|
35
|
+
options = {
|
|
36
|
+
maxDepth: 1,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let { minDepth, maxDepth = false, depth = false, root, noRoot = false } = options
|
|
41
|
+
|
|
42
|
+
if (!is.number(maxDepth)) {
|
|
43
|
+
maxDepth = is.number(depth) ? depth : 200_000
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!is.number(minDepth)) {
|
|
47
|
+
minDepth = 0
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!is.array(dir) && !is.string(dir)) {
|
|
51
|
+
throw error(`${libName}: need an array or a string as first argument`, 'E_ARG_TYPE')
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (is.empty(dir)) {
|
|
55
|
+
throw error(`${libName}: first argument can not be empty`, 'E_ARG_EMPTY')
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (is.empty(root) && is.string(dir)) {
|
|
59
|
+
root = dir
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
if (is.array(dir)) {
|
|
64
|
+
const dirs = await Promise.all(dir.map(async f => await getDirectories(f, options)))
|
|
65
|
+
|
|
66
|
+
return deep.flatten(...dirs).filter(a => a)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const currentDepth = dir
|
|
70
|
+
.replace(root || process.cwd(), '')
|
|
71
|
+
.split(path.sep)
|
|
72
|
+
.filter(a => a).length
|
|
73
|
+
|
|
74
|
+
if (currentDepth > maxDepth) {
|
|
75
|
+
return []
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const dirContent = await fs.readdir(dir)
|
|
79
|
+
|
|
80
|
+
/** @type {string[]} */
|
|
81
|
+
const dirs = []
|
|
82
|
+
|
|
83
|
+
await Promise.all(
|
|
84
|
+
dirContent.map(async file => {
|
|
85
|
+
if (!is.string(file)) {
|
|
86
|
+
throw error(`${libName}: path was not a string: ${file}`, 'E_ARG_TYPE')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let filePath = await getFilePath(getDirectories, dir, file, { maxDepth, minDepth, root })
|
|
90
|
+
|
|
91
|
+
if (filePath) {
|
|
92
|
+
if (!is.array(filePath)) {
|
|
93
|
+
filePath = [filePath]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
await Promise.all(
|
|
97
|
+
filePath.map(async file => {
|
|
98
|
+
try {
|
|
99
|
+
const stat = await fs.stat(file)
|
|
100
|
+
if (stat.isDirectory()) {
|
|
101
|
+
if (is.array(filePath)) {
|
|
102
|
+
dirs.push(...filePath)
|
|
103
|
+
} else if (is.string(filePath)) {
|
|
104
|
+
dirs.push(filePath)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
} catch (statErr) {
|
|
108
|
+
// File might have been deleted between readdir and stat
|
|
109
|
+
// Just skip it
|
|
110
|
+
}
|
|
111
|
+
}),
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
}),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
let finalDirs = deep.flatten(dirs).filter(a => a)
|
|
118
|
+
if (!noRoot) {
|
|
119
|
+
finalDirs = [dir, ...finalDirs]
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const finalized = finalDirs
|
|
123
|
+
.filter(a => is.string(a))
|
|
124
|
+
.filter(dir => {
|
|
125
|
+
const currentDepth = dir
|
|
126
|
+
.replace(root || process.cwd(), '')
|
|
127
|
+
.split(path.sep)
|
|
128
|
+
.filter(a => a).length
|
|
129
|
+
|
|
130
|
+
return currentDepth >= minDepth
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
const unique = Array.from(new Set(finalized))
|
|
134
|
+
|
|
135
|
+
return unique
|
|
136
|
+
} catch (e) {
|
|
137
|
+
const err = /** @type {import('@magic/error').CustomError} */ (e)
|
|
138
|
+
if (err.code === 'ENOENT') {
|
|
139
|
+
return []
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
throw e
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -1,12 +1,27 @@
|
|
|
1
|
-
import path from 'path'
|
|
1
|
+
import path from 'node:path'
|
|
2
2
|
|
|
3
3
|
import is from '@magic/types'
|
|
4
4
|
import error from '@magic/error'
|
|
5
5
|
|
|
6
|
-
import { fs } from './fs.
|
|
6
|
+
import { fs } from './fs.js'
|
|
7
7
|
|
|
8
8
|
const libName = '@magic/fs.getFilePath'
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {typeof import('./getFiles.js').getFiles} GetFiles
|
|
12
|
+
* @typedef {import('./getFiles.js').Options} GetFilesOptions
|
|
13
|
+
* @typedef {typeof import('./getDirectories.js').getDirectories} GetDirectories
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @param {GetFiles | GetDirectories} fn
|
|
20
|
+
* @param {string} dir
|
|
21
|
+
* @param {string} file
|
|
22
|
+
* @param {GetFilesOptions} args
|
|
23
|
+
* @returns {Promise<string | string[] | undefined>}
|
|
24
|
+
*/
|
|
10
25
|
export const getFilePath = async (fn, dir, file, args = {}) => {
|
|
11
26
|
if (is.empty(fn)) {
|
|
12
27
|
throw error(`${libName}: fn: first argument can not be empty`, 'E_ARG_1_EMPTY')
|
|
@@ -32,7 +47,7 @@ export const getFilePath = async (fn, dir, file, args = {}) => {
|
|
|
32
47
|
const filePath = path.join(dir, file)
|
|
33
48
|
|
|
34
49
|
const stat = await fs.stat(filePath)
|
|
35
|
-
if (stat.isDirectory(
|
|
50
|
+
if (stat.isDirectory()) {
|
|
36
51
|
return await fn(filePath, args)
|
|
37
52
|
} else if (stat.isFile()) {
|
|
38
53
|
return filePath
|
package/src/getFiles.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
|
|
3
|
+
// import deep from '@magic/deep'
|
|
4
|
+
import is from '@magic/types'
|
|
5
|
+
import error from '@magic/error'
|
|
6
|
+
|
|
7
|
+
import { getFilePath } from './getFilePath.js'
|
|
8
|
+
import { fs } from './fs.js'
|
|
9
|
+
|
|
10
|
+
const libName = '@magic/fs.getFiles'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {object} Options
|
|
14
|
+
* @property {number} [minDepth]
|
|
15
|
+
* @property {number} [maxDepth]
|
|
16
|
+
* @property {number | false} [depth]
|
|
17
|
+
* @property {string} [extension]
|
|
18
|
+
* @property {string} [ext]
|
|
19
|
+
* @property {string} [root]
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} dir
|
|
24
|
+
* First argument: directory to scan
|
|
25
|
+
* @param {number | Options} [options]
|
|
26
|
+
* If number, sets maxDepth directly.
|
|
27
|
+
* @returns {Promise<string[]>}
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
export const getFiles = async (dir, options = {}) => {
|
|
31
|
+
if (is.number(options)) {
|
|
32
|
+
options = {
|
|
33
|
+
maxDepth: options,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let {
|
|
38
|
+
minDepth = 0,
|
|
39
|
+
maxDepth = false,
|
|
40
|
+
depth = false,
|
|
41
|
+
extension = false,
|
|
42
|
+
ext = false,
|
|
43
|
+
root = process.cwd(),
|
|
44
|
+
} = options
|
|
45
|
+
|
|
46
|
+
if (ext && !extension) {
|
|
47
|
+
extension = ext
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!is.number(maxDepth)) {
|
|
51
|
+
maxDepth = is.number(depth) ? depth : 200_000
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!is.number(minDepth)) {
|
|
55
|
+
minDepth = 0
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (is.empty(dir)) {
|
|
59
|
+
throw error(`${libName}: dir: first argument can not be empty.`, 'E_ARG_EMPTY')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!is.string(dir)) {
|
|
63
|
+
throw error(`${libName}: dir: first argument must be a string.`, 'E_ARG_TYPE')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (is.empty(root)) {
|
|
67
|
+
root = dir
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const currentDepth =
|
|
71
|
+
dir
|
|
72
|
+
.replace(root, '')
|
|
73
|
+
.split(path.sep)
|
|
74
|
+
.filter(a => a).length - 1
|
|
75
|
+
|
|
76
|
+
if (currentDepth > maxDepth) {
|
|
77
|
+
return []
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
const dirContent = await fs.readdir(dir)
|
|
82
|
+
const files = await Promise.all(
|
|
83
|
+
dirContent.map(file => getFilePath(getFiles, dir, file, { maxDepth, minDepth, root })),
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
const flatFiles = files
|
|
87
|
+
.flat(20000)
|
|
88
|
+
.filter(a => !is.undef(a))
|
|
89
|
+
/*
|
|
90
|
+
* if an extension parameter has been passed,
|
|
91
|
+
* remove the file if it does not end with extension
|
|
92
|
+
*/
|
|
93
|
+
.filter(a => !extension || a.endsWith(extension))
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
* filter nonfiles - use async stat
|
|
97
|
+
*/
|
|
98
|
+
const fileStats = await Promise.all(
|
|
99
|
+
flatFiles.map(async f => {
|
|
100
|
+
try {
|
|
101
|
+
const stat = await fs.stat(f)
|
|
102
|
+
return { path: f, isFile: stat.isFile() }
|
|
103
|
+
} catch {
|
|
104
|
+
return { path: f, isFile: false }
|
|
105
|
+
}
|
|
106
|
+
}),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
fileStats
|
|
111
|
+
.filter(({ isFile }) => isFile)
|
|
112
|
+
.map(({ path }) => path)
|
|
113
|
+
/*
|
|
114
|
+
* filter files if depth is smaller than minDepth
|
|
115
|
+
*/
|
|
116
|
+
.filter(file => {
|
|
117
|
+
const currentDepth =
|
|
118
|
+
file
|
|
119
|
+
.replace(root ?? '', '')
|
|
120
|
+
.split(path.sep)
|
|
121
|
+
.filter(a => a).length - 1
|
|
122
|
+
|
|
123
|
+
return currentDepth >= minDepth
|
|
124
|
+
})
|
|
125
|
+
)
|
|
126
|
+
} catch (e) {
|
|
127
|
+
const err = /** @type {Error & { code?: string }} */ (e)
|
|
128
|
+
if (err.code === 'ENOENT') {
|
|
129
|
+
return []
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
throw error(err.message, err.code)
|
|
133
|
+
}
|
|
134
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { fs as fso } from './fs.js'
|
|
2
|
+
|
|
3
|
+
import { mkdirp } from './mkdirp.js'
|
|
4
|
+
import { rmrf } from './rmrf.js'
|
|
5
|
+
import { getFileType } from './getFileType.js'
|
|
6
|
+
import { getDirectories } from './getDirectories.js'
|
|
7
|
+
import { getFiles } from './getFiles.js'
|
|
8
|
+
import { exists } from './exists.js'
|
|
9
|
+
import { getContentType } from './getContentType.js'
|
|
10
|
+
import { getFilePath } from './getFilePath.js'
|
|
11
|
+
|
|
12
|
+
export const fs = /** @type {const} */ ({
|
|
13
|
+
...fso,
|
|
14
|
+
mkdirp,
|
|
15
|
+
rmrf,
|
|
16
|
+
getFileType,
|
|
17
|
+
getDirectories,
|
|
18
|
+
getFiles,
|
|
19
|
+
exists,
|
|
20
|
+
getContentType,
|
|
21
|
+
getFilePath,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
export default fs
|
|
@@ -3,10 +3,15 @@ import path from 'path'
|
|
|
3
3
|
import error from '@magic/error'
|
|
4
4
|
import is from '@magic/types'
|
|
5
5
|
|
|
6
|
-
import { fs } from './fs.
|
|
6
|
+
import { fs } from './fs.js'
|
|
7
7
|
|
|
8
8
|
const libName = '@magic/fs.mkdirp'
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* @param {string} p
|
|
13
|
+
* @returns {Promise<boolean | void>}
|
|
14
|
+
*/
|
|
10
15
|
export const mkdirp = async p => {
|
|
11
16
|
if (is.empty(p)) {
|
|
12
17
|
throw error(`${libName} expects a non-empty path string as argument.`, 'E_ARG_EMPTY')
|
|
@@ -29,10 +34,11 @@ export const mkdirp = async p => {
|
|
|
29
34
|
await fs.mkdir(p)
|
|
30
35
|
return true
|
|
31
36
|
} catch (e) {
|
|
32
|
-
|
|
37
|
+
const err = /** @type {Error & { code?: string}} */ (e)
|
|
38
|
+
if (err.code === 'EEXIST') {
|
|
33
39
|
return true
|
|
34
40
|
}
|
|
35
41
|
|
|
36
|
-
throw error(
|
|
42
|
+
throw error(err)
|
|
37
43
|
}
|
|
38
44
|
}
|
package/src/{rmrf.mjs → rmrf.js}
RENAMED
|
@@ -3,12 +3,25 @@ import path from 'path'
|
|
|
3
3
|
import is from '@magic/types'
|
|
4
4
|
import error from '@magic/error'
|
|
5
5
|
|
|
6
|
-
import { fs } from './fs.
|
|
6
|
+
import { fs } from './fs.js'
|
|
7
7
|
|
|
8
8
|
const cwd = process.cwd()
|
|
9
9
|
|
|
10
10
|
const libName = '@magic/fs.rmrf'
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {object} Options
|
|
14
|
+
* @property {boolean} [dryRun]
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Recursively removes a file or directory.
|
|
19
|
+
*
|
|
20
|
+
* @throws {Error} If the argument is invalid, outside cwd, or fs operations fail.
|
|
21
|
+
* @param {string} dir
|
|
22
|
+
* @param {Options} [opts]
|
|
23
|
+
* @returns {Promise<boolean | undefined>}
|
|
24
|
+
*/
|
|
12
25
|
export const rmrf = async (dir, opts = {}) => {
|
|
13
26
|
if (is.empty(dir)) {
|
|
14
27
|
throw error(`${libName}: expecting a non-empty argument.`, 'E_DIR_EMPTY')
|
|
@@ -45,10 +58,12 @@ export const rmrf = async (dir, opts = {}) => {
|
|
|
45
58
|
return true
|
|
46
59
|
}
|
|
47
60
|
} catch (e) {
|
|
48
|
-
|
|
61
|
+
const err = /** @type {Error & { code?: string}} */ (e)
|
|
62
|
+
|
|
63
|
+
if (err.code === 'ENOENT') {
|
|
49
64
|
return true
|
|
50
65
|
}
|
|
51
66
|
|
|
52
|
-
throw error(
|
|
67
|
+
throw error(err)
|
|
53
68
|
}
|
|
54
69
|
}
|
package/types/fs.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export const fs: {
|
|
2
|
+
readonly exists: typeof fso.exists.__promisify__
|
|
3
|
+
readonly readdir: typeof fso.promises.readdir
|
|
4
|
+
readonly readDir: typeof fso.promises.readdir
|
|
5
|
+
readonly readFile: typeof fso.promises.readFile
|
|
6
|
+
readonly readfile: typeof fso.promises.readFile
|
|
7
|
+
readonly rmdir: typeof fso.promises.rmdir
|
|
8
|
+
readonly rmDir: typeof fso.promises.rmdir
|
|
9
|
+
readonly watch: typeof fso.watch
|
|
10
|
+
readonly access: typeof fso.promises.access
|
|
11
|
+
readonly copyFile: typeof fso.promises.copyFile
|
|
12
|
+
readonly open: typeof fso.promises.open
|
|
13
|
+
readonly rename: typeof fso.promises.rename
|
|
14
|
+
readonly truncate: typeof fso.promises.truncate
|
|
15
|
+
readonly rm: typeof fso.promises.rm
|
|
16
|
+
readonly mkdir: typeof fso.promises.mkdir
|
|
17
|
+
readonly readlink: typeof fso.promises.readlink
|
|
18
|
+
readonly symlink: typeof fso.promises.symlink
|
|
19
|
+
readonly lstat: typeof fso.promises.lstat
|
|
20
|
+
readonly stat: typeof fso.promises.stat
|
|
21
|
+
readonly statfs: typeof fso.promises.statfs
|
|
22
|
+
readonly link: typeof fso.promises.link
|
|
23
|
+
readonly unlink: typeof fso.promises.unlink
|
|
24
|
+
readonly chmod: typeof fso.promises.chmod
|
|
25
|
+
readonly lchmod: typeof fso.promises.lchmod
|
|
26
|
+
readonly lchown: typeof fso.promises.lchown
|
|
27
|
+
readonly lutimes: typeof fso.promises.lutimes
|
|
28
|
+
readonly chown: typeof fso.promises.chown
|
|
29
|
+
readonly utimes: typeof fso.promises.utimes
|
|
30
|
+
readonly realpath: typeof fso.promises.realpath
|
|
31
|
+
readonly mkdtemp: typeof fso.promises.mkdtemp
|
|
32
|
+
readonly mkdtempDisposable: typeof fso.promises.mkdtempDisposable
|
|
33
|
+
readonly writeFile: typeof fso.promises.writeFile
|
|
34
|
+
readonly appendFile: typeof fso.promises.appendFile
|
|
35
|
+
readonly opendir: typeof fso.promises.opendir
|
|
36
|
+
readonly cp: typeof fso.promises.cp
|
|
37
|
+
readonly glob: typeof fso.promises.glob
|
|
38
|
+
readonly constants: typeof fso.constants
|
|
39
|
+
readonly renameSync: typeof fso.renameSync
|
|
40
|
+
readonly truncateSync: typeof fso.truncateSync
|
|
41
|
+
readonly ftruncate: typeof fso.ftruncate
|
|
42
|
+
readonly ftruncateSync: typeof fso.ftruncateSync
|
|
43
|
+
readonly chownSync: typeof fso.chownSync
|
|
44
|
+
readonly fchown: typeof fso.fchown
|
|
45
|
+
readonly fchownSync: typeof fso.fchownSync
|
|
46
|
+
readonly lchownSync: typeof fso.lchownSync
|
|
47
|
+
readonly lutimesSync: typeof fso.lutimesSync
|
|
48
|
+
readonly chmodSync: typeof fso.chmodSync
|
|
49
|
+
readonly fchmod: typeof fso.fchmod
|
|
50
|
+
readonly fchmodSync: typeof fso.fchmodSync
|
|
51
|
+
readonly lchmodSync: typeof fso.lchmodSync
|
|
52
|
+
readonly fstat: typeof fso.fstat
|
|
53
|
+
readonly fstatSync: typeof fso.fstatSync
|
|
54
|
+
readonly statfsSync: typeof fso.statfsSync
|
|
55
|
+
readonly linkSync: typeof fso.linkSync
|
|
56
|
+
readonly symlinkSync: typeof fso.symlinkSync
|
|
57
|
+
readonly readlinkSync: typeof fso.readlinkSync
|
|
58
|
+
readonly realpathSync: typeof fso.realpathSync
|
|
59
|
+
readonly unlinkSync: typeof fso.unlinkSync
|
|
60
|
+
readonly rmdirSync: typeof fso.rmdirSync
|
|
61
|
+
readonly rmSync: typeof fso.rmSync
|
|
62
|
+
readonly mkdirSync: typeof fso.mkdirSync
|
|
63
|
+
readonly mkdtempSync: typeof fso.mkdtempSync
|
|
64
|
+
readonly mkdtempDisposableSync: typeof fso.mkdtempDisposableSync
|
|
65
|
+
readonly readdirSync: typeof fso.readdirSync
|
|
66
|
+
readonly close: typeof fso.close
|
|
67
|
+
readonly closeSync: typeof fso.closeSync
|
|
68
|
+
readonly openSync: typeof fso.openSync
|
|
69
|
+
readonly utimesSync: typeof fso.utimesSync
|
|
70
|
+
readonly futimes: typeof fso.futimes
|
|
71
|
+
readonly futimesSync: typeof fso.futimesSync
|
|
72
|
+
readonly fsync: typeof fso.fsync
|
|
73
|
+
readonly fsyncSync: typeof fso.fsyncSync
|
|
74
|
+
readonly write: typeof fso.write
|
|
75
|
+
readonly writeSync: typeof fso.writeSync
|
|
76
|
+
readonly read: typeof fso.read
|
|
77
|
+
readonly readSync: typeof fso.readSync
|
|
78
|
+
readonly readFileSync: typeof fso.readFileSync
|
|
79
|
+
readonly writeFileSync: typeof fso.writeFileSync
|
|
80
|
+
readonly appendFileSync: typeof fso.appendFileSync
|
|
81
|
+
readonly watchFile: typeof fso.watchFile
|
|
82
|
+
readonly unwatchFile: typeof fso.unwatchFile
|
|
83
|
+
readonly existsSync: typeof fso.existsSync
|
|
84
|
+
readonly accessSync: typeof fso.accessSync
|
|
85
|
+
readonly createReadStream: typeof fso.createReadStream
|
|
86
|
+
readonly createWriteStream: typeof fso.createWriteStream
|
|
87
|
+
readonly fdatasync: typeof fso.fdatasync
|
|
88
|
+
readonly fdatasyncSync: typeof fso.fdatasyncSync
|
|
89
|
+
readonly copyFileSync: typeof fso.copyFileSync
|
|
90
|
+
readonly writev: typeof fso.writev
|
|
91
|
+
readonly writevSync: typeof fso.writevSync
|
|
92
|
+
readonly readv: typeof fso.readv
|
|
93
|
+
readonly readvSync: typeof fso.readvSync
|
|
94
|
+
readonly openAsBlob: typeof fso.openAsBlob
|
|
95
|
+
readonly opendirSync: typeof fso.opendirSync
|
|
96
|
+
readonly cpSync: typeof fso.cpSync
|
|
97
|
+
readonly globSync: typeof fso.globSync
|
|
98
|
+
readonly promises: typeof fso.promises
|
|
99
|
+
readonly Stats: typeof fso.Stats
|
|
100
|
+
readonly StatsFs: typeof fso.StatsFs
|
|
101
|
+
readonly Dirent: typeof fso.Dirent
|
|
102
|
+
readonly Dir: typeof fso.Dir
|
|
103
|
+
readonly ReadStream: typeof fso.ReadStream
|
|
104
|
+
readonly Utf8Stream: typeof fso.Utf8Stream
|
|
105
|
+
readonly WriteStream: typeof fso.WriteStream
|
|
106
|
+
readonly statSync: fso.StatSyncFn
|
|
107
|
+
readonly lstatSync: fso.StatSyncFn
|
|
108
|
+
}
|
|
109
|
+
import fso from 'node:fs'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function getContentType(uri: string): string
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function getDirectories(
|
|
2
|
+
dir: string | string[],
|
|
3
|
+
options?: number | false | Options,
|
|
4
|
+
): Promise<string[]>
|
|
5
|
+
export type Options = {
|
|
6
|
+
root?: string | undefined
|
|
7
|
+
maxDepth?: number | undefined
|
|
8
|
+
minDepth?: number | undefined
|
|
9
|
+
depth?: number | boolean | undefined
|
|
10
|
+
noRoot?: boolean | undefined
|
|
11
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function getFilePath(
|
|
2
|
+
fn: GetFiles | GetDirectories,
|
|
3
|
+
dir: string,
|
|
4
|
+
file: string,
|
|
5
|
+
args?: GetFilesOptions,
|
|
6
|
+
): Promise<string | string[] | undefined>
|
|
7
|
+
export type GetFiles = typeof import('./getFiles.js').getFiles
|
|
8
|
+
export type GetFilesOptions = import('./getFiles.js').Options
|
|
9
|
+
export type GetDirectories = typeof import('./getDirectories.js').getDirectories
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function getFileType(name: string): string
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function getFiles(dir: string, options?: number | Options): Promise<string[]>
|
|
2
|
+
export type Options = {
|
|
3
|
+
minDepth?: number | undefined
|
|
4
|
+
maxDepth?: number | undefined
|
|
5
|
+
depth?: number | false | undefined
|
|
6
|
+
extension?: string | undefined
|
|
7
|
+
ext?: string | undefined
|
|
8
|
+
root?: string | undefined
|
|
9
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
export const fs: {
|
|
2
|
+
readonly mkdirp: (p: string) => Promise<boolean | void>
|
|
3
|
+
readonly rmrf: (dir: string, opts?: Options) => Promise<boolean | undefined>
|
|
4
|
+
readonly getFileType: (name: string) => string
|
|
5
|
+
readonly getDirectories: (
|
|
6
|
+
dir: string | string[],
|
|
7
|
+
options?: number | false | Options,
|
|
8
|
+
) => Promise<string[]>
|
|
9
|
+
readonly getFiles: (dir: string, options?: number | Options) => Promise<string[]>
|
|
10
|
+
readonly exists: (f: import('fs').PathLike) => Promise<boolean>
|
|
11
|
+
readonly getContentType: (uri: string) => string
|
|
12
|
+
readonly getFilePath: (
|
|
13
|
+
fn: GetFiles | GetDirectories,
|
|
14
|
+
dir: string,
|
|
15
|
+
file: string,
|
|
16
|
+
args?: GetFilesOptions,
|
|
17
|
+
) => Promise<string | string[] | undefined>
|
|
18
|
+
readonly readdir: typeof import('fs/promises').readdir
|
|
19
|
+
readonly readDir: typeof import('fs/promises').readdir
|
|
20
|
+
readonly readFile: typeof import('fs/promises').readFile
|
|
21
|
+
readonly readfile: typeof import('fs/promises').readFile
|
|
22
|
+
readonly rmdir: typeof import('fs/promises').rmdir
|
|
23
|
+
readonly rmDir: typeof import('fs/promises').rmdir
|
|
24
|
+
readonly watch: typeof import('fs').watch
|
|
25
|
+
readonly access: typeof import('fs/promises').access
|
|
26
|
+
readonly copyFile: typeof import('fs/promises').copyFile
|
|
27
|
+
readonly open: typeof import('fs/promises').open
|
|
28
|
+
readonly rename: typeof import('fs/promises').rename
|
|
29
|
+
readonly truncate: typeof import('fs/promises').truncate
|
|
30
|
+
readonly rm: typeof import('fs/promises').rm
|
|
31
|
+
readonly mkdir: typeof import('fs/promises').mkdir
|
|
32
|
+
readonly readlink: typeof import('fs/promises').readlink
|
|
33
|
+
readonly symlink: typeof import('fs/promises').symlink
|
|
34
|
+
readonly lstat: typeof import('fs/promises').lstat
|
|
35
|
+
readonly stat: typeof import('fs/promises').stat
|
|
36
|
+
readonly statfs: typeof import('fs/promises').statfs
|
|
37
|
+
readonly link: typeof import('fs/promises').link
|
|
38
|
+
readonly unlink: typeof import('fs/promises').unlink
|
|
39
|
+
readonly chmod: typeof import('fs/promises').chmod
|
|
40
|
+
readonly lchmod: typeof import('fs/promises').lchmod
|
|
41
|
+
readonly lchown: typeof import('fs/promises').lchown
|
|
42
|
+
readonly lutimes: typeof import('fs/promises').lutimes
|
|
43
|
+
readonly chown: typeof import('fs/promises').chown
|
|
44
|
+
readonly utimes: typeof import('fs/promises').utimes
|
|
45
|
+
readonly realpath: typeof import('fs/promises').realpath
|
|
46
|
+
readonly mkdtemp: typeof import('fs/promises').mkdtemp
|
|
47
|
+
readonly mkdtempDisposable: typeof import('fs/promises').mkdtempDisposable
|
|
48
|
+
readonly writeFile: typeof import('fs/promises').writeFile
|
|
49
|
+
readonly appendFile: typeof import('fs/promises').appendFile
|
|
50
|
+
readonly opendir: typeof import('fs/promises').opendir
|
|
51
|
+
readonly cp: typeof import('fs/promises').cp
|
|
52
|
+
readonly glob: typeof import('fs/promises').glob
|
|
53
|
+
readonly constants: typeof import('fs').constants
|
|
54
|
+
readonly renameSync: typeof import('fs').renameSync
|
|
55
|
+
readonly truncateSync: typeof import('fs').truncateSync
|
|
56
|
+
readonly ftruncate: typeof import('fs').ftruncate
|
|
57
|
+
readonly ftruncateSync: typeof import('fs').ftruncateSync
|
|
58
|
+
readonly chownSync: typeof import('fs').chownSync
|
|
59
|
+
readonly fchown: typeof import('fs').fchown
|
|
60
|
+
readonly fchownSync: typeof import('fs').fchownSync
|
|
61
|
+
readonly lchownSync: typeof import('fs').lchownSync
|
|
62
|
+
readonly lutimesSync: typeof import('fs').lutimesSync
|
|
63
|
+
readonly chmodSync: typeof import('fs').chmodSync
|
|
64
|
+
readonly fchmod: typeof import('fs').fchmod
|
|
65
|
+
readonly fchmodSync: typeof import('fs').fchmodSync
|
|
66
|
+
readonly lchmodSync: typeof import('fs').lchmodSync
|
|
67
|
+
readonly fstat: typeof import('fs').fstat
|
|
68
|
+
readonly fstatSync: typeof import('fs').fstatSync
|
|
69
|
+
readonly statfsSync: typeof import('fs').statfsSync
|
|
70
|
+
readonly linkSync: typeof import('fs').linkSync
|
|
71
|
+
readonly symlinkSync: typeof import('fs').symlinkSync
|
|
72
|
+
readonly readlinkSync: typeof import('fs').readlinkSync
|
|
73
|
+
readonly realpathSync: typeof import('fs').realpathSync
|
|
74
|
+
readonly unlinkSync: typeof import('fs').unlinkSync
|
|
75
|
+
readonly rmdirSync: typeof import('fs').rmdirSync
|
|
76
|
+
readonly rmSync: typeof import('fs').rmSync
|
|
77
|
+
readonly mkdirSync: typeof import('fs').mkdirSync
|
|
78
|
+
readonly mkdtempSync: typeof import('fs').mkdtempSync
|
|
79
|
+
readonly mkdtempDisposableSync: typeof import('fs').mkdtempDisposableSync
|
|
80
|
+
readonly readdirSync: typeof import('fs').readdirSync
|
|
81
|
+
readonly close: typeof import('fs').close
|
|
82
|
+
readonly closeSync: typeof import('fs').closeSync
|
|
83
|
+
readonly openSync: typeof import('fs').openSync
|
|
84
|
+
readonly utimesSync: typeof import('fs').utimesSync
|
|
85
|
+
readonly futimes: typeof import('fs').futimes
|
|
86
|
+
readonly futimesSync: typeof import('fs').futimesSync
|
|
87
|
+
readonly fsync: typeof import('fs').fsync
|
|
88
|
+
readonly fsyncSync: typeof import('fs').fsyncSync
|
|
89
|
+
readonly write: typeof import('fs').write
|
|
90
|
+
readonly writeSync: typeof import('fs').writeSync
|
|
91
|
+
readonly read: typeof import('fs').read
|
|
92
|
+
readonly readSync: typeof import('fs').readSync
|
|
93
|
+
readonly readFileSync: typeof import('fs').readFileSync
|
|
94
|
+
readonly writeFileSync: typeof import('fs').writeFileSync
|
|
95
|
+
readonly appendFileSync: typeof import('fs').appendFileSync
|
|
96
|
+
readonly watchFile: typeof import('fs').watchFile
|
|
97
|
+
readonly unwatchFile: typeof import('fs').unwatchFile
|
|
98
|
+
readonly existsSync: typeof import('fs').existsSync
|
|
99
|
+
readonly accessSync: typeof import('fs').accessSync
|
|
100
|
+
readonly createReadStream: typeof import('fs').createReadStream
|
|
101
|
+
readonly createWriteStream: typeof import('fs').createWriteStream
|
|
102
|
+
readonly fdatasync: typeof import('fs').fdatasync
|
|
103
|
+
readonly fdatasyncSync: typeof import('fs').fdatasyncSync
|
|
104
|
+
readonly copyFileSync: typeof import('fs').copyFileSync
|
|
105
|
+
readonly writev: typeof import('fs').writev
|
|
106
|
+
readonly writevSync: typeof import('fs').writevSync
|
|
107
|
+
readonly readv: typeof import('fs').readv
|
|
108
|
+
readonly readvSync: typeof import('fs').readvSync
|
|
109
|
+
readonly openAsBlob: typeof import('fs').openAsBlob
|
|
110
|
+
readonly opendirSync: typeof import('fs').opendirSync
|
|
111
|
+
readonly cpSync: typeof import('fs').cpSync
|
|
112
|
+
readonly globSync: typeof import('fs').globSync
|
|
113
|
+
readonly promises: typeof import('node:fs/promises')
|
|
114
|
+
readonly Stats: typeof import('fs').Stats
|
|
115
|
+
readonly StatsFs: typeof import('fs').StatsFs
|
|
116
|
+
readonly Dirent: typeof import('fs').Dirent
|
|
117
|
+
readonly Dir: typeof import('fs').Dir
|
|
118
|
+
readonly ReadStream: typeof import('fs').ReadStream
|
|
119
|
+
readonly Utf8Stream: typeof import('fs').Utf8Stream
|
|
120
|
+
readonly WriteStream: typeof import('fs').WriteStream
|
|
121
|
+
readonly statSync: import('fs').StatSyncFn
|
|
122
|
+
readonly lstatSync: import('fs').StatSyncFn
|
|
123
|
+
}
|
|
124
|
+
export default fs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function mkdirp(p: string): Promise<boolean | void>
|
package/types/rmrf.d.ts
ADDED
package/src/contentTypes.mjs
DELETED
package/src/getDirectories.mjs
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
|
|
3
|
-
import is from '@magic/types'
|
|
4
|
-
import deep from '@magic/deep'
|
|
5
|
-
import error from '@magic/error'
|
|
6
|
-
import log from '@magic/log'
|
|
7
|
-
|
|
8
|
-
import { fs } from './fs.mjs'
|
|
9
|
-
|
|
10
|
-
import { getFilePath } from './getFilePath.mjs'
|
|
11
|
-
|
|
12
|
-
const libName = '@magic/fs.getDirectories'
|
|
13
|
-
|
|
14
|
-
export const getDirectories = async (dir, args = {}) => {
|
|
15
|
-
if (is.number(args)) {
|
|
16
|
-
args = {
|
|
17
|
-
maxDepth: args,
|
|
18
|
-
}
|
|
19
|
-
} else if (args === false) {
|
|
20
|
-
args = {
|
|
21
|
-
maxDepth: 1,
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let { minDepth, maxDepth = false, depth = false, root, noRoot = false } = args
|
|
26
|
-
|
|
27
|
-
if (is.number(depth) && !is.number(maxDepth)) {
|
|
28
|
-
maxDepth = depth
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (!is.number(maxDepth)) {
|
|
32
|
-
maxDepth = 200_000
|
|
33
|
-
}
|
|
34
|
-
if (!is.number(minDepth)) {
|
|
35
|
-
minDepth = 0
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!is.array(dir) && !is.string(dir)) {
|
|
39
|
-
throw error(`${libName}: need an array or a string as first argument`, 'E_ARG_TYPE')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (is.empty(dir)) {
|
|
43
|
-
throw error(`${libName}: first argument can not be empty`, 'E_ARG_EMPTY')
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (is.empty(root)) {
|
|
47
|
-
if (is.string(dir)) {
|
|
48
|
-
root = dir
|
|
49
|
-
} else {
|
|
50
|
-
root = process.cwd()
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
if (is.array(dir)) {
|
|
56
|
-
const dirs = await Promise.all(
|
|
57
|
-
dir.map(async f => await getDirectories(f, { maxDepth, minDepth, root, noRoot })),
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
return deep.flatten(...dirs).filter(a => a)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const currentDepth = dir
|
|
64
|
-
.replace(root, '')
|
|
65
|
-
.split(path.sep)
|
|
66
|
-
.filter(a => a).length
|
|
67
|
-
|
|
68
|
-
if (currentDepth > maxDepth) {
|
|
69
|
-
return []
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const dirContent = await fs.readdir(dir)
|
|
73
|
-
|
|
74
|
-
const dirs = await Promise.all(
|
|
75
|
-
dirContent.map(async file => {
|
|
76
|
-
if (!is.string(file)) {
|
|
77
|
-
throw error(`${libName}: path was not a string: ${file}`, 'E_ARG_TYPE')
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let filePath = await getFilePath(getDirectories, dir, file, { maxDepth, minDepth, root })
|
|
81
|
-
|
|
82
|
-
if (filePath) {
|
|
83
|
-
if (!is.array(filePath)) {
|
|
84
|
-
filePath = [filePath]
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const files = await Promise.all(
|
|
88
|
-
filePath.map(async file => {
|
|
89
|
-
if (!is.string(file)) {
|
|
90
|
-
throw error(`${libName}: path was not a string: ${file}`, 'E_ARG_TYPE')
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const stat = await fs.stat(file)
|
|
94
|
-
if (stat.isDirectory()) {
|
|
95
|
-
return filePath
|
|
96
|
-
}
|
|
97
|
-
}),
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
return files
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return
|
|
104
|
-
}),
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
let finalDirs = deep.flatten(dirs).filter(a => a)
|
|
108
|
-
if (!noRoot) {
|
|
109
|
-
finalDirs = [dir, ...finalDirs]
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const finalized = finalDirs
|
|
113
|
-
.filter(a => a)
|
|
114
|
-
.filter(dir => {
|
|
115
|
-
if (is.number(minDepth)) {
|
|
116
|
-
const currentDepth = dir
|
|
117
|
-
.replace(root, '')
|
|
118
|
-
.split(path.sep)
|
|
119
|
-
.filter(a => a).length
|
|
120
|
-
|
|
121
|
-
return currentDepth >= minDepth
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return false
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
const unique = Array.from(new Set(finalized))
|
|
128
|
-
|
|
129
|
-
return unique
|
|
130
|
-
} catch (e) {
|
|
131
|
-
if (e.code === 'ENOENT') {
|
|
132
|
-
return []
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
throw e
|
|
136
|
-
}
|
|
137
|
-
}
|
package/src/getFiles.mjs
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
|
|
3
|
-
import deep from '@magic/deep'
|
|
4
|
-
import is from '@magic/types'
|
|
5
|
-
import error from '@magic/error'
|
|
6
|
-
|
|
7
|
-
import { getFilePath } from './getFilePath.mjs'
|
|
8
|
-
import { fs } from './fs.mjs'
|
|
9
|
-
|
|
10
|
-
const libName = '@magic/fs.getFiles'
|
|
11
|
-
|
|
12
|
-
export const getFiles = async (dir, args = {}) => {
|
|
13
|
-
if (is.number(args)) {
|
|
14
|
-
args = {
|
|
15
|
-
maxDepth: args,
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
let { minDepth = 0, maxDepth = false, depth = false, extension = false, ext = false, root } = args
|
|
20
|
-
|
|
21
|
-
if (ext && !extension) {
|
|
22
|
-
extension = ext
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (is.number(depth) && !is.number(maxDepth)) {
|
|
26
|
-
maxDepth = depth
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (!is.number(maxDepth)) {
|
|
30
|
-
maxDepth = 200_000
|
|
31
|
-
}
|
|
32
|
-
if (!is.number(minDepth)) {
|
|
33
|
-
minDepth = 0
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (is.empty(dir)) {
|
|
37
|
-
throw error(`${libName}: dir: first argument can not be empty.`, 'E_ARG_EMPTY')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (!is.string(dir)) {
|
|
41
|
-
throw error(`${libName}: dir: first argument must be a string.`, 'E_ARG_TYPE')
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (is.empty(root)) {
|
|
45
|
-
root = dir
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const currentDepth = dir
|
|
49
|
-
.replace(root, '')
|
|
50
|
-
.split(path.sep)
|
|
51
|
-
.filter(a => a).length
|
|
52
|
-
|
|
53
|
-
if (currentDepth > maxDepth) {
|
|
54
|
-
return []
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
const dirContent = await fs.readdir(dir)
|
|
59
|
-
const files = await Promise.all(
|
|
60
|
-
dirContent.map(file => getFilePath(getFiles, dir, file, { maxDepth, minDepth, root })),
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
return await Promise.all(
|
|
64
|
-
deep
|
|
65
|
-
.flatten(files)
|
|
66
|
-
.filter(a => a)
|
|
67
|
-
/*
|
|
68
|
-
* if an extension parameter has been passed,
|
|
69
|
-
* remove the file if it does not end with extension
|
|
70
|
-
*/
|
|
71
|
-
.filter(a => !extension || a.endsWith(extension))
|
|
72
|
-
/*
|
|
73
|
-
* filter nonfiles
|
|
74
|
-
*/
|
|
75
|
-
.filter(async f => {
|
|
76
|
-
const stat = await fs.stat(f)
|
|
77
|
-
return stat.isFile()
|
|
78
|
-
})
|
|
79
|
-
/*
|
|
80
|
-
* filter files if depth is smaller than minDepth
|
|
81
|
-
*/
|
|
82
|
-
.filter(file => {
|
|
83
|
-
if (!file) {
|
|
84
|
-
return false
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (is.number(minDepth)) {
|
|
88
|
-
const currentDepth =
|
|
89
|
-
file
|
|
90
|
-
.replace(root, '')
|
|
91
|
-
.split(path.sep)
|
|
92
|
-
.filter(a => a).length - 1
|
|
93
|
-
|
|
94
|
-
return currentDepth >= minDepth
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return true
|
|
98
|
-
}),
|
|
99
|
-
)
|
|
100
|
-
} catch (e) {
|
|
101
|
-
if (e.code === 'ENOENT') {
|
|
102
|
-
return []
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
throw error(e.message, e.code)
|
|
106
|
-
}
|
|
107
|
-
}
|
package/src/index.mjs
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { fs as fso } from './fs.mjs'
|
|
2
|
-
|
|
3
|
-
import { mkdirp } from './mkdirp.mjs'
|
|
4
|
-
import { rmrf } from './rmrf.mjs'
|
|
5
|
-
import { getFileType } from './getFileType.mjs'
|
|
6
|
-
import { getDirectories } from './getDirectories.mjs'
|
|
7
|
-
import { getFiles } from './getFiles.mjs'
|
|
8
|
-
import { exists } from './exists.mjs'
|
|
9
|
-
import { getContentType } from './getContentType.mjs'
|
|
10
|
-
import { getFilePath } from './getFilePath.mjs'
|
|
11
|
-
|
|
12
|
-
export const fs = {
|
|
13
|
-
...fso,
|
|
14
|
-
mkdirp,
|
|
15
|
-
rmrf,
|
|
16
|
-
getFileType,
|
|
17
|
-
getDirectories,
|
|
18
|
-
getFiles,
|
|
19
|
-
exists,
|
|
20
|
-
getContentType,
|
|
21
|
-
getFilePath,
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export default fs
|