@appium/support 2.58.0 → 2.59.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/build/lib/console.d.ts +110 -0
- package/build/lib/console.d.ts.map +1 -0
- package/build/lib/console.js +113 -0
- package/build/lib/env.d.ts.map +1 -1
- package/build/lib/env.js +1 -1
- package/build/lib/fs.d.ts.map +1 -1
- package/build/lib/fs.js +1 -1
- package/build/lib/image-util.d.ts.map +1 -1
- package/build/lib/image-util.js +1 -1
- package/build/lib/index.d.ts +3 -1
- package/build/lib/index.js +8 -3
- package/build/lib/log-internal.d.ts.map +1 -1
- package/build/lib/log-internal.js +1 -1
- package/build/lib/logger.d.ts +1 -1
- package/build/lib/logger.d.ts.map +1 -1
- package/build/lib/logger.js +1 -1
- package/build/lib/logging.d.ts +11 -4
- package/build/lib/logging.d.ts.map +1 -1
- package/build/lib/logging.js +7 -6
- package/build/lib/mjpeg.d.ts.map +1 -1
- package/build/lib/mjpeg.js +1 -1
- package/build/lib/mkdirp.js +1 -1
- package/build/lib/net.d.ts +5 -2
- package/build/lib/net.d.ts.map +1 -1
- package/build/lib/net.js +1 -1
- package/build/lib/node.d.ts.map +1 -1
- package/build/lib/node.js +1 -1
- package/build/lib/npm.d.ts.map +1 -1
- package/build/lib/npm.js +1 -1
- package/build/lib/plist.d.ts +1 -1
- package/build/lib/plist.d.ts.map +1 -1
- package/build/lib/plist.js +1 -1
- package/build/lib/process.d.ts.map +1 -1
- package/build/lib/process.js +1 -1
- package/build/lib/system.js +1 -1
- package/build/lib/tempdir.d.ts.map +1 -1
- package/build/lib/tempdir.js +1 -1
- package/build/lib/timing.d.ts.map +1 -1
- package/build/lib/timing.js +1 -1
- package/build/lib/util.d.ts +19 -2
- package/build/lib/util.d.ts.map +1 -1
- package/build/lib/util.js +3 -7
- package/build/lib/zip.d.ts +5 -5
- package/build/lib/zip.d.ts.map +1 -1
- package/build/lib/zip.js +2 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/console.js +173 -0
- package/lib/env.js +12 -14
- package/lib/fs.js +87 -62
- package/lib/image-util.js +50 -32
- package/lib/index.js +39 -8
- package/lib/log-internal.js +16 -11
- package/lib/logger.js +1 -1
- package/lib/logging.js +32 -30
- package/lib/mjpeg.js +32 -27
- package/lib/mkdirp.js +3 -3
- package/lib/net.js +60 -52
- package/lib/node.js +22 -17
- package/lib/npm.js +50 -47
- package/lib/plist.js +34 -18
- package/lib/process.js +8 -6
- package/lib/system.js +8 -8
- package/lib/tempdir.js +14 -9
- package/lib/timing.js +12 -15
- package/lib/util.js +121 -72
- package/lib/zip.js +88 -92
- package/package.json +9 -8
package/lib/console.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import {supportsColor} from 'supports-color';
|
|
3
|
+
import {Console as NodeConsole} from 'console';
|
|
4
|
+
import '@colors/colors';
|
|
5
|
+
import symbols from 'log-symbols';
|
|
6
|
+
import {Writable} from 'stream';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Stream to nowhere. Used when we want to disable any output other than JSON output.
|
|
10
|
+
*/
|
|
11
|
+
class NullWritable extends Writable {
|
|
12
|
+
// eslint-disable-next-line promise/prefer-await-to-callbacks
|
|
13
|
+
_write(chunk, encoding, callback) {
|
|
14
|
+
setImmediate(callback);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A particular console/logging class for Appium's CLI.
|
|
20
|
+
*
|
|
21
|
+
* - By default, uses some fancy symbols
|
|
22
|
+
* - Writes to `STDERR`, generally.
|
|
23
|
+
* - In "JSON mode", `STDERR` is squelched. Use {@linkcode Console.json} to write the JSON.
|
|
24
|
+
*
|
|
25
|
+
* DO NOT extend this to do anything other than what it already does. Download a library or something.
|
|
26
|
+
*/
|
|
27
|
+
export class CliConsole {
|
|
28
|
+
/**
|
|
29
|
+
* Internal console
|
|
30
|
+
* @type {globalThis.Console}
|
|
31
|
+
*/
|
|
32
|
+
#console;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Whether or not to use fancy symbols when logging.
|
|
36
|
+
* @type {boolean}
|
|
37
|
+
*
|
|
38
|
+
*/
|
|
39
|
+
#useSymbols;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whether or not to use color.
|
|
43
|
+
*/
|
|
44
|
+
#useColor;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @type {Record<keyof typeof symbols,keyof Extract<import('@colors/colors').Color, 'string'>>}
|
|
48
|
+
*/
|
|
49
|
+
static symbolToColor = {
|
|
50
|
+
success: 'green',
|
|
51
|
+
info: 'cyan',
|
|
52
|
+
warning: 'yellow',
|
|
53
|
+
error: 'red',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param {ConsoleOpts} opts
|
|
59
|
+
*/
|
|
60
|
+
constructor({jsonMode = false, useSymbols = true, useColor} = {}) {
|
|
61
|
+
this.#console = new NodeConsole(process.stdout, jsonMode ? new NullWritable() : process.stderr);
|
|
62
|
+
this.#useSymbols = Boolean(useSymbols);
|
|
63
|
+
this.#useColor = Boolean(useColor ?? supportsColor(process.stderr));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Wraps a message string in breathtaking fanciness
|
|
68
|
+
*
|
|
69
|
+
* Returns `undefined` if `msg` is `undefined`.
|
|
70
|
+
* @param {string} [msg] - Message to decorate, if anything
|
|
71
|
+
* @param {keyof typeof CliConsole['symbolToColor']} [symbol] - Symbol to use
|
|
72
|
+
* @returns {string|undefined}
|
|
73
|
+
*/
|
|
74
|
+
decorate(msg, symbol) {
|
|
75
|
+
if (_.isString(msg)) {
|
|
76
|
+
let newMsg = /** @type {string} */ (msg);
|
|
77
|
+
if (_.isString(symbol) && this.#useSymbols) {
|
|
78
|
+
newMsg = `${symbols[symbol]} ${newMsg}`;
|
|
79
|
+
if (this.#useColor) {
|
|
80
|
+
newMsg = newMsg[CliConsole.symbolToColor[symbol]];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return newMsg;
|
|
84
|
+
}
|
|
85
|
+
return msg;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Writes to `STDOUT`. Must be stringifyable.
|
|
90
|
+
*
|
|
91
|
+
* You probably don't want to call this more than once before exiting (since that will output invalid JSON).
|
|
92
|
+
* @param {import('type-fest').JsonValue} value
|
|
93
|
+
*/
|
|
94
|
+
json(value) {
|
|
95
|
+
this.#console.log(JSON.stringify(value));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* General logging function.
|
|
100
|
+
* @param {string} [message]
|
|
101
|
+
* @param {...any} args
|
|
102
|
+
*/
|
|
103
|
+
log(message, ...args) {
|
|
104
|
+
this.#console.error(message, ...args);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* A "success" message
|
|
109
|
+
* @param {string} [message]
|
|
110
|
+
* @param {...any} args
|
|
111
|
+
*/
|
|
112
|
+
ok(message, ...args) {
|
|
113
|
+
this.#console.error(this.decorate(message, 'success'), ...args);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Alias for {@linkcode Console.log}
|
|
118
|
+
* @param {string} [message]
|
|
119
|
+
* @param {...any} args
|
|
120
|
+
*/
|
|
121
|
+
debug(message, ...args) {
|
|
122
|
+
this.log(message, ...args);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Wraps {@link console.dir}
|
|
127
|
+
* @param {any} item
|
|
128
|
+
* @param {import('util').InspectOptions} [opts]
|
|
129
|
+
*/
|
|
130
|
+
dump(item, opts) {
|
|
131
|
+
this.#console.dir(item, opts);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* An "info" message
|
|
136
|
+
* @param {string} [message]
|
|
137
|
+
* @param {...any} args
|
|
138
|
+
*/
|
|
139
|
+
info(message, ...args) {
|
|
140
|
+
this.log(this.decorate(message, 'info'), ...args);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* A "warning" message
|
|
145
|
+
* @param {string} [message]
|
|
146
|
+
* @param {...any} args
|
|
147
|
+
*/
|
|
148
|
+
warn(message, ...args) {
|
|
149
|
+
this.log(this.decorate(message, 'warning'), ...args);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* An "error" message
|
|
154
|
+
* @param {string} [message]
|
|
155
|
+
* @param {...any} args
|
|
156
|
+
*/
|
|
157
|
+
error(message, ...args) {
|
|
158
|
+
this.log(this.decorate(message, 'error'), ...args);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Options for {@linkcode CliConsole}.
|
|
164
|
+
*
|
|
165
|
+
* @typedef ConsoleOpts
|
|
166
|
+
* @property {boolean} [jsonMode] - If _truthy_, supress all output except JSON (use {@linkcode CliConsole#json}), which writes to `STDOUT`.
|
|
167
|
+
* @property {boolean} [useSymbols] - If _falsy_, do not use fancy symbols.
|
|
168
|
+
* @property {boolean} [useColor] - If _falsy_, do not use color output. If _truthy_, forces color output. By default, checks terminal/TTY for support via pkg `supports-color`. Ignored if `useSymbols` is `false`.
|
|
169
|
+
* @see https://npm.im/supports-color
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
export const console = new CliConsole();
|
|
173
|
+
export {symbols};
|
package/lib/env.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import _ from 'lodash';
|
|
3
|
-
import {
|
|
3
|
+
import {homedir} from 'os';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import pkgDir from 'pkg-dir';
|
|
6
6
|
import readPkg from 'read-pkg';
|
|
7
|
-
import {
|
|
7
|
+
import {npm} from './npm';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Path to the default `APPIUM_HOME` dir (`~/.appium`).
|
|
@@ -26,7 +26,7 @@ export const MANIFEST_RELATIVE_PATH = path.join(
|
|
|
26
26
|
'node_modules',
|
|
27
27
|
'.cache',
|
|
28
28
|
'appium',
|
|
29
|
-
MANIFEST_BASENAME
|
|
29
|
+
MANIFEST_BASENAME
|
|
30
30
|
);
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -45,7 +45,7 @@ export const MANIFEST_RELATIVE_PATH = path.join(
|
|
|
45
45
|
* @param {string} cwd
|
|
46
46
|
* @returns {Promise<boolean>}
|
|
47
47
|
*/
|
|
48
|
-
export async function hasAppiumDependency
|
|
48
|
+
export async function hasAppiumDependency(cwd) {
|
|
49
49
|
/**
|
|
50
50
|
* @todo type this
|
|
51
51
|
* @type {object}
|
|
@@ -78,7 +78,7 @@ export async function hasAppiumDependency (cwd) {
|
|
|
78
78
|
// doing any further checking here may be a fool's errand, because you can pin the version
|
|
79
79
|
// to a _lot_ of different things (tags, URLs, etc).
|
|
80
80
|
!version.startsWith('1') &&
|
|
81
|
-
!version.startsWith('0')
|
|
81
|
+
!version.startsWith('0')
|
|
82
82
|
);
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -91,9 +91,9 @@ export const readPackageInDir = _.memoize(
|
|
|
91
91
|
* @param {string} cwd - Directory ostensibly having a `package.json`
|
|
92
92
|
* @returns {Promise<import('read-pkg').NormalizedPackageJson|undefined>}
|
|
93
93
|
*/
|
|
94
|
-
async function _readPackageInDir
|
|
94
|
+
async function _readPackageInDir(cwd) {
|
|
95
95
|
return await readPkg({cwd, normalize: true});
|
|
96
|
-
}
|
|
96
|
+
}
|
|
97
97
|
);
|
|
98
98
|
|
|
99
99
|
/**
|
|
@@ -108,7 +108,7 @@ export const resolveAppiumHome = _.memoize(
|
|
|
108
108
|
* @param {string} [cwd] - Current working directory. _Must_ be absolute, if specified.
|
|
109
109
|
* @returns {Promise<string>}
|
|
110
110
|
*/
|
|
111
|
-
async function _resolveAppiumHome
|
|
111
|
+
async function _resolveAppiumHome(cwd = process.cwd()) {
|
|
112
112
|
if (process.env.APPIUM_HOME) {
|
|
113
113
|
return process.env.APPIUM_HOME;
|
|
114
114
|
}
|
|
@@ -133,10 +133,8 @@ export const resolveAppiumHome = _.memoize(
|
|
|
133
133
|
return DEFAULT_APPIUM_HOME;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
return (await hasAppiumDependency(currentPkgDir))
|
|
137
|
-
|
|
138
|
-
: DEFAULT_APPIUM_HOME;
|
|
139
|
-
},
|
|
136
|
+
return (await hasAppiumDependency(currentPkgDir)) ? currentPkgDir : DEFAULT_APPIUM_HOME;
|
|
137
|
+
}
|
|
140
138
|
);
|
|
141
139
|
|
|
142
140
|
/**
|
|
@@ -150,11 +148,11 @@ export const resolveManifestPath = _.memoize(
|
|
|
150
148
|
* @param {string} [appiumHome] - Appium home directory
|
|
151
149
|
* @returns {Promise<string>}
|
|
152
150
|
*/
|
|
153
|
-
async function _resolveManifestPath
|
|
151
|
+
async function _resolveManifestPath(appiumHome) {
|
|
154
152
|
// can you "await" in a default parameter? is that a good idea?
|
|
155
153
|
appiumHome = appiumHome ?? (await resolveAppiumHome());
|
|
156
154
|
return path.join(appiumHome, MANIFEST_RELATIVE_PATH);
|
|
157
|
-
}
|
|
155
|
+
}
|
|
158
156
|
);
|
|
159
157
|
|
|
160
158
|
/**
|
package/lib/fs.js
CHANGED
|
@@ -2,7 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import B from 'bluebird';
|
|
4
4
|
import crypto from 'crypto';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
close,
|
|
7
|
+
constants,
|
|
8
|
+
createReadStream,
|
|
9
|
+
createWriteStream,
|
|
10
|
+
promises as fsPromises,
|
|
11
|
+
read,
|
|
12
|
+
write,
|
|
13
|
+
open,
|
|
14
|
+
} from 'fs';
|
|
6
15
|
import glob from 'glob';
|
|
7
16
|
import klaw from 'klaw';
|
|
8
17
|
import _ from 'lodash';
|
|
@@ -16,9 +25,12 @@ import sanitize from 'sanitize-filename';
|
|
|
16
25
|
import which from 'which';
|
|
17
26
|
import log from './logger';
|
|
18
27
|
import Timer from './timing';
|
|
19
|
-
import {
|
|
28
|
+
import {pluralize} from './util';
|
|
20
29
|
|
|
21
|
-
const ncpAsync =
|
|
30
|
+
const ncpAsync =
|
|
31
|
+
/** @type {(source: string, dest: string, opts: ncp.Options|undefined) => B<void>} */ (
|
|
32
|
+
B.promisify(ncp)
|
|
33
|
+
);
|
|
22
34
|
const findRootCached = _.memoize(pkgDir.sync);
|
|
23
35
|
|
|
24
36
|
const fs = {
|
|
@@ -27,7 +39,7 @@ const fs = {
|
|
|
27
39
|
* @param {import('fs').PathLike} path
|
|
28
40
|
* @returns {Promise<boolean>}
|
|
29
41
|
*/
|
|
30
|
-
async hasAccess
|
|
42
|
+
async hasAccess(path) {
|
|
31
43
|
try {
|
|
32
44
|
await fsPromises.access(path, constants.R_OK);
|
|
33
45
|
} catch (err) {
|
|
@@ -40,7 +52,7 @@ const fs = {
|
|
|
40
52
|
* Alias for {@linkcode fs.hasAccess}
|
|
41
53
|
* @param {import('fs').PathLike} path
|
|
42
54
|
*/
|
|
43
|
-
async exists
|
|
55
|
+
async exists(path) {
|
|
44
56
|
return await fs.hasAccess(path);
|
|
45
57
|
},
|
|
46
58
|
|
|
@@ -48,7 +60,9 @@ const fs = {
|
|
|
48
60
|
* Remove a directory and all its contents, recursively
|
|
49
61
|
* @todo Replace with `rm()` from `fs.promises` when Node.js v12 support is dropped.
|
|
50
62
|
*/
|
|
51
|
-
rimraf: /** @type {(dirpath: string, opts?: import('rimraf').Options) => Promise<void>} */(
|
|
63
|
+
rimraf: /** @type {(dirpath: string, opts?: import('rimraf').Options) => Promise<void>} */ (
|
|
64
|
+
B.promisify(rimrafIdx)
|
|
65
|
+
),
|
|
52
66
|
|
|
53
67
|
/**
|
|
54
68
|
* Alias of {@linkcode rimrafIdx.sync}
|
|
@@ -64,7 +78,7 @@ const fs = {
|
|
|
64
78
|
* @returns {Promise<string|undefined>}
|
|
65
79
|
* @see https://nodejs.org/api/fs.html#fspromisesmkdirpath-options
|
|
66
80
|
*/
|
|
67
|
-
async mkdir
|
|
81
|
+
async mkdir(filepath, opts = {}) {
|
|
68
82
|
try {
|
|
69
83
|
return await fsPromises.mkdir(filepath, opts);
|
|
70
84
|
} catch (err) {
|
|
@@ -81,8 +95,8 @@ const fs = {
|
|
|
81
95
|
* @see https://npm.im/ncp
|
|
82
96
|
* @returns {Promise<void>}
|
|
83
97
|
*/
|
|
84
|
-
async copyFile
|
|
85
|
-
if (!await fs.hasAccess(source)) {
|
|
98
|
+
async copyFile(source, destination, opts = {}) {
|
|
99
|
+
if (!(await fs.hasAccess(source))) {
|
|
86
100
|
throw new Error(`The file at '${source}' does not exist or is not accessible`);
|
|
87
101
|
}
|
|
88
102
|
return await ncpAsync(source, destination, opts);
|
|
@@ -93,14 +107,14 @@ const fs = {
|
|
|
93
107
|
* @param {import('fs').PathLike} filePath
|
|
94
108
|
* @returns {Promise<string>}
|
|
95
109
|
*/
|
|
96
|
-
async md5
|
|
110
|
+
async md5(filePath) {
|
|
97
111
|
return await fs.hash(filePath, 'md5');
|
|
98
112
|
},
|
|
99
113
|
|
|
100
114
|
/**
|
|
101
115
|
* Move a file
|
|
102
116
|
*/
|
|
103
|
-
mv: /** @type {(from: string, to: string, opts?: mv.Options) => B<void>} */(B.promisify(mv)),
|
|
117
|
+
mv: /** @type {(from: string, to: string, opts?: mv.Options) => B<void>} */ (B.promisify(mv)),
|
|
104
118
|
|
|
105
119
|
/**
|
|
106
120
|
* Find path to an executable in system `PATH`
|
|
@@ -112,7 +126,7 @@ const fs = {
|
|
|
112
126
|
* Given a glob pattern, resolve with list of files matching that pattern
|
|
113
127
|
* @see https://github.com/isaacs/node-glob
|
|
114
128
|
*/
|
|
115
|
-
glob: /** @type {(pattern: string, opts?: glob.IOptions) => B<string[]>} */(B.promisify(glob)),
|
|
129
|
+
glob: /** @type {(pattern: string, opts?: glob.IOptions) => B<string[]>} */ (B.promisify(glob)),
|
|
116
130
|
|
|
117
131
|
/**
|
|
118
132
|
* Sanitize a filename
|
|
@@ -126,12 +140,17 @@ const fs = {
|
|
|
126
140
|
* @param {string} [algorithm]
|
|
127
141
|
* @returns {Promise<string>}
|
|
128
142
|
*/
|
|
129
|
-
async hash
|
|
143
|
+
async hash(filePath, algorithm = 'sha1') {
|
|
130
144
|
return await new B((resolve, reject) => {
|
|
131
145
|
const fileHash = crypto.createHash(algorithm);
|
|
132
146
|
const readStream = createReadStream(filePath);
|
|
133
|
-
readStream.on('error', (e) =>
|
|
134
|
-
|
|
147
|
+
readStream.on('error', (e) =>
|
|
148
|
+
reject(
|
|
149
|
+
new Error(
|
|
150
|
+
`Cannot calculate ${algorithm} hash for '${filePath}'. Original error: ${e.message}`
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
);
|
|
135
154
|
readStream.on('data', (chunk) => fileHash.update(chunk));
|
|
136
155
|
readStream.on('end', () => resolve(fileHash.digest('hex')));
|
|
137
156
|
});
|
|
@@ -145,7 +164,7 @@ const fs = {
|
|
|
145
164
|
* @returns {import('klaw').Walker}
|
|
146
165
|
* @see https://www.npmjs.com/package/klaw
|
|
147
166
|
*/
|
|
148
|
-
walk
|
|
167
|
+
walk(dir, opts) {
|
|
149
168
|
return klaw(dir, opts);
|
|
150
169
|
},
|
|
151
170
|
|
|
@@ -154,7 +173,7 @@ const fs = {
|
|
|
154
173
|
* @param {import('fs').PathLike} dir
|
|
155
174
|
* @returns {Promise<string|undefined>}
|
|
156
175
|
*/
|
|
157
|
-
async mkdirp
|
|
176
|
+
async mkdirp(dir) {
|
|
158
177
|
return await fs.mkdir(dir, {recursive: true});
|
|
159
178
|
},
|
|
160
179
|
|
|
@@ -166,7 +185,8 @@ const fs = {
|
|
|
166
185
|
* @throws {Error} If the `dir` parameter contains a path to an invalid folder
|
|
167
186
|
* @returns {Promise<string?>} returns the found path or null if the item was not found
|
|
168
187
|
*/
|
|
169
|
-
async walkDir
|
|
188
|
+
async walkDir(dir, recursive, callback) {
|
|
189
|
+
//eslint-disable-line promise/prefer-await-to-callbacks
|
|
170
190
|
let isValidRoot = false;
|
|
171
191
|
let errMsg = null;
|
|
172
192
|
try {
|
|
@@ -175,7 +195,9 @@ const fs = {
|
|
|
175
195
|
errMsg = e.message;
|
|
176
196
|
}
|
|
177
197
|
if (!isValidRoot) {
|
|
178
|
-
throw Error(
|
|
198
|
+
throw Error(
|
|
199
|
+
`'${dir}' is not a valid root directory` + (errMsg ? `. Original error: ${errMsg}` : '')
|
|
200
|
+
);
|
|
179
201
|
}
|
|
180
202
|
|
|
181
203
|
let walker;
|
|
@@ -187,48 +209,51 @@ const fs = {
|
|
|
187
209
|
walker = klaw(dir, {
|
|
188
210
|
depthLimit: recursive ? -1 : 0,
|
|
189
211
|
});
|
|
190
|
-
walker
|
|
191
|
-
|
|
212
|
+
walker
|
|
213
|
+
.on('data', function (item) {
|
|
214
|
+
walker.pause();
|
|
192
215
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
216
|
+
if (!item.stats.isDirectory()) {
|
|
217
|
+
fileCount++;
|
|
218
|
+
} else {
|
|
219
|
+
directoryCount++;
|
|
220
|
+
}
|
|
198
221
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
reject(err);
|
|
216
|
-
}
|
|
217
|
-
})
|
|
218
|
-
.on('end', function () {
|
|
219
|
-
lastFileProcessed
|
|
220
|
-
.then((file) => {
|
|
221
|
-
resolve(/** @type {string|undefined} */(file) ?? null);
|
|
222
|
-
})
|
|
223
|
-
.catch(function (err) {
|
|
224
|
-
log.warn(`Unexpected error: ${err.message}`);
|
|
222
|
+
// eslint-disable-next-line promise/prefer-await-to-callbacks
|
|
223
|
+
lastFileProcessed = B.try(async () => await callback(item.path, item.stats.isDirectory()))
|
|
224
|
+
.then(function (done = false) {
|
|
225
|
+
if (done) {
|
|
226
|
+
resolve(item.path);
|
|
227
|
+
} else {
|
|
228
|
+
walker.resume();
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
.catch(reject);
|
|
232
|
+
})
|
|
233
|
+
.on('error', function (err, item) {
|
|
234
|
+
log.warn(`Got an error while walking '${item.path}': ${err.message}`);
|
|
235
|
+
// klaw cannot get back from an ENOENT error
|
|
236
|
+
if (err.code === 'ENOENT') {
|
|
237
|
+
log.warn('All files may not have been accessed');
|
|
225
238
|
reject(err);
|
|
226
|
-
}
|
|
227
|
-
|
|
239
|
+
}
|
|
240
|
+
})
|
|
241
|
+
.on('end', function () {
|
|
242
|
+
lastFileProcessed
|
|
243
|
+
.then((file) => {
|
|
244
|
+
resolve(/** @type {string|undefined} */ (file) ?? null);
|
|
245
|
+
})
|
|
246
|
+
.catch(function (err) {
|
|
247
|
+
log.warn(`Unexpected error: ${err.message}`);
|
|
248
|
+
reject(err);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
228
251
|
}).finally(function () {
|
|
229
|
-
log.debug(
|
|
230
|
-
`
|
|
231
|
-
|
|
252
|
+
log.debug(
|
|
253
|
+
`Traversed ${pluralize('directory', directoryCount, true)} ` +
|
|
254
|
+
`and ${pluralize('file', fileCount, true)} ` +
|
|
255
|
+
`in ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`
|
|
256
|
+
);
|
|
232
257
|
if (walker) {
|
|
233
258
|
walker.destroy();
|
|
234
259
|
}
|
|
@@ -241,7 +266,7 @@ const fs = {
|
|
|
241
266
|
* @throws {Error} If there were problems finding or reading a `package.json` file
|
|
242
267
|
* @returns {object} A parsed `package.json`
|
|
243
268
|
*/
|
|
244
|
-
readPackageJsonFrom
|
|
269
|
+
readPackageJsonFrom(dir, opts = {}) {
|
|
245
270
|
const cwd = fs.findRoot(dir);
|
|
246
271
|
try {
|
|
247
272
|
return readPkg.sync({...opts, cwd});
|
|
@@ -257,7 +282,7 @@ const fs = {
|
|
|
257
282
|
* @throws {Error} If there were problems finding the project root
|
|
258
283
|
* @returns {string} The closeset parent dir containing `package.json`
|
|
259
284
|
*/
|
|
260
|
-
findRoot
|
|
285
|
+
findRoot(dir) {
|
|
261
286
|
if (!dir || !path.isAbsolute(dir)) {
|
|
262
287
|
throw new TypeError('`findRoot()` must be provided a non-empty, absolute path');
|
|
263
288
|
}
|
|
@@ -320,10 +345,10 @@ const fs = {
|
|
|
320
345
|
* Use `constants.X_OK` instead.
|
|
321
346
|
* @deprecated
|
|
322
347
|
*/
|
|
323
|
-
X_OK: constants.X_OK
|
|
348
|
+
X_OK: constants.X_OK,
|
|
324
349
|
};
|
|
325
350
|
|
|
326
|
-
export {
|
|
351
|
+
export {fs};
|
|
327
352
|
export default fs;
|
|
328
353
|
|
|
329
354
|
/**
|
|
@@ -332,7 +357,7 @@ export default fs;
|
|
|
332
357
|
* @param {string} itemPath The path of the file or folder
|
|
333
358
|
* @param {boolean} isDirectory Shows if it is a directory or a file
|
|
334
359
|
* @return {boolean} return true if you want to stop walking
|
|
335
|
-
*/
|
|
360
|
+
*/
|
|
336
361
|
|
|
337
362
|
/**
|
|
338
363
|
* @typedef {import('glob')} glob
|