@appium/support 7.0.4 → 7.0.6
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 +42 -88
- package/build/lib/console.d.ts.map +1 -1
- package/build/lib/console.js +25 -85
- package/build/lib/console.js.map +1 -1
- package/build/lib/doctor.d.ts +6 -18
- package/build/lib/doctor.d.ts.map +1 -1
- package/build/lib/doctor.js +0 -15
- package/build/lib/doctor.js.map +1 -1
- package/build/lib/env.d.ts +14 -20
- package/build/lib/env.d.ts.map +1 -1
- package/build/lib/env.js +24 -61
- package/build/lib/env.js.map +1 -1
- package/build/lib/fs.d.ts +109 -148
- package/build/lib/fs.d.ts.map +1 -1
- package/build/lib/fs.js +130 -230
- package/build/lib/fs.js.map +1 -1
- package/build/lib/image-util.d.ts +7 -6
- package/build/lib/image-util.d.ts.map +1 -1
- package/build/lib/image-util.js +9 -6
- package/build/lib/image-util.js.map +1 -1
- package/build/lib/index.d.ts +19 -17
- package/build/lib/index.d.ts.map +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/logger.js.map +1 -1
- package/build/lib/logging.d.ts +7 -15
- package/build/lib/logging.d.ts.map +1 -1
- package/build/lib/logging.js +36 -62
- package/build/lib/logging.js.map +1 -1
- package/build/lib/mjpeg.d.ts +19 -56
- package/build/lib/mjpeg.d.ts.map +1 -1
- package/build/lib/mjpeg.js +55 -78
- package/build/lib/mjpeg.js.map +1 -1
- package/build/lib/mkdirp.d.ts +4 -1
- package/build/lib/mkdirp.d.ts.map +1 -1
- package/build/lib/mkdirp.js +1 -2
- package/build/lib/mkdirp.js.map +1 -1
- package/build/lib/net.d.ts +52 -90
- package/build/lib/net.d.ts.map +1 -1
- package/build/lib/net.js +104 -193
- package/build/lib/net.js.map +1 -1
- package/build/lib/node.d.ts +16 -17
- package/build/lib/node.d.ts.map +1 -1
- package/build/lib/node.js +115 -120
- package/build/lib/node.js.map +1 -1
- package/build/lib/npm.d.ts +65 -86
- package/build/lib/npm.d.ts.map +1 -1
- package/build/lib/npm.js +64 -122
- package/build/lib/npm.js.map +1 -1
- package/build/lib/plist.d.ts +36 -29
- package/build/lib/plist.d.ts.map +1 -1
- package/build/lib/plist.js +62 -59
- package/build/lib/plist.js.map +1 -1
- package/build/lib/process.d.ts +19 -2
- package/build/lib/process.d.ts.map +1 -1
- package/build/lib/process.js +24 -7
- package/build/lib/process.js.map +1 -1
- package/build/lib/system.d.ts +41 -6
- package/build/lib/system.d.ts.map +1 -1
- package/build/lib/system.js +49 -14
- package/build/lib/system.js.map +1 -1
- package/build/lib/tempdir.d.ts +26 -49
- package/build/lib/tempdir.d.ts.map +1 -1
- package/build/lib/tempdir.js +46 -78
- package/build/lib/tempdir.js.map +1 -1
- package/build/lib/timing.d.ts +28 -22
- package/build/lib/timing.d.ts.map +1 -1
- package/build/lib/timing.js +16 -17
- package/build/lib/timing.js.map +1 -1
- package/build/lib/util.d.ts +164 -181
- package/build/lib/util.d.ts.map +1 -1
- package/build/lib/util.js +198 -253
- package/build/lib/util.js.map +1 -1
- package/build/lib/zip.d.ts +81 -139
- package/build/lib/zip.d.ts.map +1 -1
- package/build/lib/zip.js +235 -283
- package/build/lib/zip.js.map +1 -1
- package/lib/console.ts +139 -0
- package/lib/{doctor.js → doctor.ts} +6 -20
- package/lib/{env.js → env.ts} +34 -62
- package/lib/fs.ts +453 -0
- package/lib/image-util.ts +40 -0
- package/lib/index.ts +1 -0
- package/lib/{logger.js → logger.ts} +1 -1
- package/lib/logging.ts +157 -0
- package/lib/mjpeg.ts +186 -0
- package/lib/{mkdirp.js → mkdirp.ts} +2 -2
- package/lib/net.ts +305 -0
- package/lib/{node.js → node.ts} +136 -135
- package/lib/npm.ts +291 -0
- package/lib/plist.ts +187 -0
- package/lib/process.ts +62 -0
- package/lib/system.ts +95 -0
- package/lib/tempdir.ts +115 -0
- package/lib/{timing.js → timing.ts} +28 -33
- package/lib/util.ts +561 -0
- package/lib/{zip.js → zip.ts} +344 -299
- package/package.json +24 -26
- package/tsconfig.json +3 -5
- package/index.js +0 -1
- package/lib/console.js +0 -173
- package/lib/fs.js +0 -496
- package/lib/image-util.js +0 -32
- package/lib/logging.js +0 -145
- package/lib/mjpeg.js +0 -207
- package/lib/net.js +0 -336
- package/lib/npm.js +0 -310
- package/lib/plist.js +0 -182
- package/lib/process.js +0 -46
- package/lib/system.js +0 -48
- package/lib/tempdir.js +0 -131
- package/lib/util.js +0 -585
package/build/lib/util.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
39
|
+
exports.GiB = exports.MiB = exports.KiB = exports.W3C_WEB_ELEMENT_IDENTIFIER = exports.uuidV5 = exports.uuidV4 = exports.uuidV3 = exports.uuidV1 = exports.shellParse = void 0;
|
|
40
40
|
exports.hasContent = hasContent;
|
|
41
41
|
exports.hasValue = hasValue;
|
|
42
42
|
exports.escapeSpace = escapeSpace;
|
|
@@ -45,178 +45,179 @@ exports.localIp = localIp;
|
|
|
45
45
|
exports.cancellableDelay = cancellableDelay;
|
|
46
46
|
exports.multiResolve = multiResolve;
|
|
47
47
|
exports.safeJsonParse = safeJsonParse;
|
|
48
|
-
exports.
|
|
48
|
+
exports.jsonStringify = jsonStringify;
|
|
49
49
|
exports.unwrapElement = unwrapElement;
|
|
50
|
+
exports.wrapElement = wrapElement;
|
|
50
51
|
exports.filterObject = filterObject;
|
|
51
52
|
exports.toReadableSizeString = toReadableSizeString;
|
|
52
53
|
exports.isSubPath = isSubPath;
|
|
53
54
|
exports.isSameDestination = isSameDestination;
|
|
54
|
-
exports.compareVersions = compareVersions;
|
|
55
55
|
exports.coerceVersion = coerceVersion;
|
|
56
|
+
exports.compareVersions = compareVersions;
|
|
56
57
|
exports.quote = quote;
|
|
57
|
-
exports.jsonStringify = jsonStringify;
|
|
58
58
|
exports.pluralize = pluralize;
|
|
59
59
|
exports.toInMemoryBase64 = toInMemoryBase64;
|
|
60
60
|
exports.getLockFileGuard = getLockFileGuard;
|
|
61
61
|
const bluebird_1 = __importDefault(require("bluebird"));
|
|
62
62
|
const lodash_1 = __importDefault(require("lodash"));
|
|
63
|
-
const
|
|
64
|
-
const
|
|
63
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
64
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
65
|
+
const node_stream_1 = __importDefault(require("node:stream"));
|
|
66
|
+
const node_util_1 = require("node:util");
|
|
67
|
+
const asyncbox_1 = require("asyncbox");
|
|
65
68
|
const fs_1 = require("./fs");
|
|
66
69
|
const semver = __importStar(require("semver"));
|
|
67
70
|
const shell_quote_1 = require("shell-quote");
|
|
68
71
|
Object.defineProperty(exports, "shellParse", { enumerable: true, get: function () { return shell_quote_1.parse; } });
|
|
69
72
|
const pluralize_1 = __importDefault(require("pluralize"));
|
|
70
|
-
const stream_1 = __importDefault(require("stream"));
|
|
71
73
|
const base64_stream_1 = require("base64-stream");
|
|
72
|
-
|
|
74
|
+
var uuid_1 = require("uuid");
|
|
73
75
|
Object.defineProperty(exports, "uuidV1", { enumerable: true, get: function () { return uuid_1.v1; } });
|
|
74
76
|
Object.defineProperty(exports, "uuidV3", { enumerable: true, get: function () { return uuid_1.v3; } });
|
|
75
77
|
Object.defineProperty(exports, "uuidV4", { enumerable: true, get: function () { return uuid_1.v4; } });
|
|
76
78
|
Object.defineProperty(exports, "uuidV5", { enumerable: true, get: function () { return uuid_1.v5; } });
|
|
77
79
|
const _lockfile = __importStar(require("lockfile"));
|
|
78
|
-
|
|
79
|
-
exports.W3C_WEB_ELEMENT_IDENTIFIER =
|
|
80
|
-
|
|
81
|
-
exports.KiB =
|
|
82
|
-
|
|
83
|
-
exports.MiB =
|
|
84
|
-
|
|
85
|
-
exports.GiB =
|
|
80
|
+
/** W3C WebDriver element identifier key used in element objects. */
|
|
81
|
+
exports.W3C_WEB_ELEMENT_IDENTIFIER = 'element-6066-11e4-a52e-4f735466cecf';
|
|
82
|
+
/** Size of one kibibyte in bytes (1024). */
|
|
83
|
+
exports.KiB = 1024;
|
|
84
|
+
/** Size of one mebibyte in bytes (1024 * 1024). */
|
|
85
|
+
exports.MiB = exports.KiB * 1024;
|
|
86
|
+
/** Size of one gibibyte in bytes (1024 * 1024 * 1024). */
|
|
87
|
+
exports.GiB = exports.MiB * 1024;
|
|
86
88
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* @
|
|
89
|
+
* Type guard: returns true if the value is a non-empty string.
|
|
90
|
+
*
|
|
91
|
+
* @param val - Value to check
|
|
92
|
+
* @returns `true` if `val` is a string with at least one character
|
|
90
93
|
*/
|
|
91
94
|
function hasContent(val) {
|
|
92
95
|
return lodash_1.default.isString(val) && val !== '';
|
|
93
96
|
}
|
|
94
97
|
/**
|
|
95
|
-
*
|
|
98
|
+
* Type guard: returns true if the value is not `undefined`, `null`, or `NaN`.
|
|
96
99
|
*
|
|
97
|
-
*
|
|
98
|
-
* @
|
|
99
|
-
* @param {T} val
|
|
100
|
-
* @returns {val is NonNullable<T>}
|
|
100
|
+
* @param val - Value to check
|
|
101
|
+
* @returns `true` if `val` is non-null and non-undefined (and not NaN for numbers)
|
|
101
102
|
*/
|
|
102
103
|
function hasValue(val) {
|
|
103
|
-
// avoid incorrectly evaluating `0` as false
|
|
104
104
|
if (lodash_1.default.isNumber(val)) {
|
|
105
105
|
return !lodash_1.default.isNaN(val);
|
|
106
106
|
}
|
|
107
107
|
return !lodash_1.default.isUndefined(val) && !lodash_1.default.isNull(val);
|
|
108
108
|
}
|
|
109
109
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* @
|
|
110
|
+
* Escapes spaces in a string for use in command-line arguments (e.g. ` ` → `\ `).
|
|
111
|
+
*
|
|
112
|
+
* @param str - String that may contain spaces
|
|
113
|
+
* @returns String with spaces escaped by a backslash
|
|
113
114
|
*/
|
|
114
115
|
function escapeSpace(str) {
|
|
115
116
|
return str.split(/ /).join('\\ ');
|
|
116
117
|
}
|
|
117
118
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* @
|
|
119
|
+
* Escapes special characters in a string (backslash, slash, quotes, control chars).
|
|
120
|
+
* If `quoteEscape` is provided, that character is also escaped.
|
|
121
|
+
*
|
|
122
|
+
* @param str - String to escape, or non-string value (returned unchanged)
|
|
123
|
+
* @param quoteEscape - Optional character to escape, or `false` to skip
|
|
124
|
+
* @returns Escaped string, or original value if `str` is not a string
|
|
122
125
|
*/
|
|
123
126
|
function escapeSpecialChars(str, quoteEscape) {
|
|
124
127
|
if (typeof str !== 'string') {
|
|
125
128
|
return str;
|
|
126
129
|
}
|
|
127
|
-
|
|
128
|
-
// @ts-ignore to set false to mark no quote escaping
|
|
129
|
-
quoteEscape = false;
|
|
130
|
-
}
|
|
131
|
-
str = str
|
|
130
|
+
const result = str
|
|
132
131
|
.replace(/[\\]/g, '\\\\')
|
|
133
|
-
.replace(/[
|
|
132
|
+
.replace(/[/]/g, '\\/')
|
|
134
133
|
.replace(/[\b]/g, '\\b')
|
|
135
134
|
.replace(/[\f]/g, '\\f')
|
|
136
135
|
.replace(/[\n]/g, '\\n')
|
|
137
136
|
.replace(/[\r]/g, '\\r')
|
|
138
137
|
.replace(/[\t]/g, '\\t')
|
|
139
|
-
.replace(/[
|
|
138
|
+
.replace(/["]/g, '\\"')
|
|
140
139
|
.replace(/\\'/g, "\\'");
|
|
141
|
-
if (quoteEscape) {
|
|
142
|
-
|
|
143
|
-
str = str.replace(re, `\\${quoteEscape}`);
|
|
140
|
+
if (!quoteEscape) {
|
|
141
|
+
return result;
|
|
144
142
|
}
|
|
145
|
-
|
|
143
|
+
const re = new RegExp(quoteEscape, 'g');
|
|
144
|
+
return result.replace(re, `\\${quoteEscape}`);
|
|
146
145
|
}
|
|
147
146
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
147
|
+
* Returns the first non-internal IPv4 address of the machine, if any.
|
|
148
|
+
*
|
|
149
|
+
* @returns The local IPv4 address, or `undefined` if none found
|
|
150
150
|
*/
|
|
151
151
|
function localIp() {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
152
|
+
const ifaces = node_os_1.default.networkInterfaces();
|
|
153
|
+
for (const addrs of Object.values(ifaces)) {
|
|
154
|
+
if (!addrs) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
for (const iface of addrs) {
|
|
158
|
+
if (iface.family === 'IPv4' && !iface.internal) {
|
|
159
|
+
return iface.address;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return undefined;
|
|
161
164
|
}
|
|
162
|
-
|
|
163
|
-
* Creates a promise that
|
|
164
|
-
*
|
|
165
|
+
/**
|
|
166
|
+
* Creates a promise that resolves after a delay and can be cancelled via `.cancel()`.
|
|
167
|
+
*
|
|
168
|
+
* @param ms - Delay in milliseconds before the promise resolves
|
|
169
|
+
* @returns A Bluebird promise with a `cancel()` method; cancel rejects with CancellationError
|
|
165
170
|
*/
|
|
171
|
+
// TODO: replace with a native implementation in Appium 4
|
|
166
172
|
function cancellableDelay(ms) {
|
|
167
173
|
let timer;
|
|
168
174
|
let resolve;
|
|
169
175
|
let reject;
|
|
170
|
-
const delay = new bluebird_1.default
|
|
176
|
+
const delay = new bluebird_1.default((_resolve, _reject) => {
|
|
171
177
|
resolve = _resolve;
|
|
172
178
|
reject = _reject;
|
|
173
|
-
timer = setTimeout(
|
|
174
|
-
resolve();
|
|
175
|
-
}, ms);
|
|
179
|
+
timer = setTimeout(() => resolve(), ms);
|
|
176
180
|
});
|
|
177
|
-
// override Bluebird's `cancel`, which does not work when using `await` on
|
|
178
|
-
// a promise, since `resolve`/`reject` are never called
|
|
179
181
|
delay.cancel = function () {
|
|
180
182
|
clearTimeout(timer);
|
|
181
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
182
183
|
reject(new bluebird_1.default.CancellationError());
|
|
183
184
|
};
|
|
184
185
|
return delay;
|
|
185
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Resolves each root path with the given path segments, returning an array of absolute paths.
|
|
189
|
+
*
|
|
190
|
+
* @param roots - Base directory paths to resolve against
|
|
191
|
+
* @param args - Path segments to join with each root (e.g. 'foo', 'bar' → root/foo/bar)
|
|
192
|
+
* @returns Array of absolute paths, one per root
|
|
193
|
+
*/
|
|
186
194
|
function multiResolve(roots, ...args) {
|
|
187
|
-
return roots.map((root) =>
|
|
195
|
+
return roots.map((root) => node_path_1.default.resolve(root, ...args));
|
|
188
196
|
}
|
|
189
197
|
/**
|
|
190
|
-
* Parses
|
|
198
|
+
* Parses a value as JSON if it is a string; otherwise returns the value as-is.
|
|
191
199
|
*
|
|
192
|
-
* @param
|
|
193
|
-
* @returns
|
|
200
|
+
* @param obj - String (to parse) or other value (returned unchanged)
|
|
201
|
+
* @returns Parsed object or original value
|
|
194
202
|
*/
|
|
195
203
|
function safeJsonParse(obj) {
|
|
196
204
|
try {
|
|
197
205
|
return JSON.parse(obj);
|
|
198
206
|
}
|
|
199
207
|
catch {
|
|
200
|
-
// ignore: this is not json parsable
|
|
201
208
|
return obj;
|
|
202
209
|
}
|
|
203
210
|
}
|
|
204
211
|
/**
|
|
205
|
-
* Stringifies
|
|
206
|
-
* display. This mimics JSON.stringify (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)
|
|
207
|
-
* except the `replacer` argument can only be a function.
|
|
212
|
+
* Stringifies an object to JSON, converting Buffers to strings for readable output.
|
|
208
213
|
*
|
|
209
|
-
* @param
|
|
210
|
-
* @param
|
|
211
|
-
*
|
|
212
|
-
* @
|
|
213
|
-
* string for readability purposes. Defaults to 2
|
|
214
|
-
* @returns {string} - the JSON object serialized as a string
|
|
214
|
+
* @param obj - Object to serialize
|
|
215
|
+
* @param replacer - Optional replacer function (same as JSON.stringify)
|
|
216
|
+
* @param space - Indentation for pretty-printing. Defaults to 2
|
|
217
|
+
* @returns JSON string
|
|
215
218
|
*/
|
|
216
219
|
function jsonStringify(obj, replacer = null, space = 2) {
|
|
217
|
-
|
|
218
|
-
const replacerFunc = lodash_1.default.isFunction(replacer) ? replacer : (k, v) => v;
|
|
219
|
-
// Buffers cannot be serialized in a readable way
|
|
220
|
+
const replacerFunc = lodash_1.default.isFunction(replacer) ? replacer : (_k, v) => v;
|
|
220
221
|
const bufferToJSON = Buffer.prototype.toJSON;
|
|
221
222
|
delete Buffer.prototype.toJSON;
|
|
222
223
|
try {
|
|
@@ -226,99 +227,100 @@ function jsonStringify(obj, replacer = null, space = 2) {
|
|
|
226
227
|
}, space);
|
|
227
228
|
}
|
|
228
229
|
finally {
|
|
229
|
-
// restore the function, so as to not break further serialization
|
|
230
230
|
Buffer.prototype.toJSON = bufferToJSON;
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
/**
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* @
|
|
238
|
-
* @returns {string}
|
|
234
|
+
* Extracts the element ID from a W3C or JSONWP element object, or returns the string if already an ID.
|
|
235
|
+
*
|
|
236
|
+
* @param el - Element object (with ELEMENT or W3C identifier) or raw element ID string
|
|
237
|
+
* @returns The element ID string
|
|
239
238
|
*/
|
|
240
239
|
function unwrapElement(el) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
240
|
+
const elObj = el;
|
|
241
|
+
for (const propName of [exports.W3C_WEB_ELEMENT_IDENTIFIER, 'ELEMENT']) {
|
|
242
|
+
if (lodash_1.default.has(elObj, propName)) {
|
|
243
|
+
return elObj[propName];
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
|
-
return
|
|
246
|
+
return el;
|
|
247
247
|
}
|
|
248
248
|
/**
|
|
249
|
+
* Wraps an element ID string in an element object compatible with both W3C and JSONWP.
|
|
249
250
|
*
|
|
250
|
-
* @param
|
|
251
|
-
* @returns
|
|
251
|
+
* @param elementId - The element ID to wrap
|
|
252
|
+
* @returns Element object with both ELEMENT and W3C identifier keys
|
|
252
253
|
*/
|
|
253
254
|
function wrapElement(elementId) {
|
|
254
255
|
return {
|
|
255
256
|
ELEMENT: elementId,
|
|
256
|
-
[W3C_WEB_ELEMENT_IDENTIFIER]: elementId,
|
|
257
|
+
[exports.W3C_WEB_ELEMENT_IDENTIFIER]: elementId,
|
|
257
258
|
};
|
|
258
259
|
}
|
|
259
|
-
|
|
260
|
-
* Returns
|
|
261
|
-
*
|
|
262
|
-
* If the predicate is
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
260
|
+
/**
|
|
261
|
+
* Returns a copy of the object containing only properties that pass the predicate.
|
|
262
|
+
* If the predicate is missing, removes properties whose values are undefined.
|
|
263
|
+
* If the predicate is a scalar, keeps only properties whose value equals that scalar.
|
|
264
|
+
* If the predicate is a function, calls it for each (value, obj) and keeps properties where it returns true.
|
|
265
|
+
*
|
|
266
|
+
* @param obj - Source object to filter
|
|
267
|
+
* @param predicate - Optional filter: undefined (drop undefined values), scalar (value match), or function
|
|
268
|
+
* @returns New object with only the properties that pass the predicate
|
|
266
269
|
*/
|
|
267
270
|
function filterObject(obj, predicate) {
|
|
268
|
-
|
|
271
|
+
const newObj = lodash_1.default.clone(obj);
|
|
272
|
+
let pred;
|
|
269
273
|
if (lodash_1.default.isUndefined(predicate)) {
|
|
270
|
-
|
|
271
|
-
predicate = (v) => !lodash_1.default.isUndefined(v);
|
|
274
|
+
pred = (v) => !lodash_1.default.isUndefined(v);
|
|
272
275
|
}
|
|
273
276
|
else if (!lodash_1.default.isFunction(predicate)) {
|
|
274
|
-
// make predicate into a function
|
|
275
277
|
const valuePredicate = predicate;
|
|
276
|
-
|
|
278
|
+
pred = (v) => v === valuePredicate;
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
pred = predicate;
|
|
277
282
|
}
|
|
278
283
|
for (const key of Object.keys(obj)) {
|
|
279
|
-
if (!
|
|
284
|
+
if (!pred(obj[key], obj)) {
|
|
280
285
|
delete newObj[key];
|
|
281
286
|
}
|
|
282
287
|
}
|
|
283
288
|
return newObj;
|
|
284
289
|
}
|
|
285
290
|
/**
|
|
286
|
-
* Converts
|
|
291
|
+
* Converts a byte count to a human-readable size string (e.g. "1.50 MB").
|
|
287
292
|
*
|
|
288
|
-
* @param
|
|
289
|
-
* @returns
|
|
290
|
-
*
|
|
291
|
-
* @throws {Error} If bytes count cannot be converted to an integer or
|
|
292
|
-
* if it is less than zero.
|
|
293
|
+
* @param bytes - Number of bytes (or string coercible to a number)
|
|
294
|
+
* @returns Formatted string like "123 B", "1.50 KB", "2.00 MB", "3.00 GB"
|
|
295
|
+
* @throws {Error} If bytes cannot be converted to a non-negative integer
|
|
293
296
|
*/
|
|
294
297
|
function toReadableSizeString(bytes) {
|
|
295
298
|
const intBytes = parseInt(String(bytes), 10);
|
|
296
299
|
if (isNaN(intBytes) || intBytes < 0) {
|
|
297
300
|
throw new Error(`Cannot convert '${bytes}' to a readable size format`);
|
|
298
301
|
}
|
|
299
|
-
if (intBytes >= GiB) {
|
|
300
|
-
return `${(intBytes / (GiB * 1.0)).toFixed(2)} GB`;
|
|
302
|
+
if (intBytes >= exports.GiB) {
|
|
303
|
+
return `${(intBytes / (exports.GiB * 1.0)).toFixed(2)} GB`;
|
|
301
304
|
}
|
|
302
|
-
else if (intBytes >= MiB) {
|
|
303
|
-
return `${(intBytes / (MiB * 1.0)).toFixed(2)} MB`;
|
|
305
|
+
else if (intBytes >= exports.MiB) {
|
|
306
|
+
return `${(intBytes / (exports.MiB * 1.0)).toFixed(2)} MB`;
|
|
304
307
|
}
|
|
305
|
-
else if (intBytes >= KiB) {
|
|
306
|
-
return `${(intBytes / (KiB * 1.0)).toFixed(2)} KB`;
|
|
308
|
+
else if (intBytes >= exports.KiB) {
|
|
309
|
+
return `${(intBytes / (exports.KiB * 1.0)).toFixed(2)} KB`;
|
|
307
310
|
}
|
|
308
311
|
return `${intBytes} B`;
|
|
309
312
|
}
|
|
310
313
|
/**
|
|
311
|
-
* Checks whether the given path is a subpath of the
|
|
312
|
-
* particular root folder. Both paths can include .. and . specifiers
|
|
314
|
+
* Checks whether the given path is a subpath of the given root folder.
|
|
313
315
|
*
|
|
314
|
-
* @param
|
|
315
|
-
* @param
|
|
316
|
-
* @param
|
|
317
|
-
* @returns
|
|
318
|
-
* @throws {Error}
|
|
316
|
+
* @param originalPath - The absolute file or folder path to test
|
|
317
|
+
* @param root - The absolute root folder path
|
|
318
|
+
* @param forcePosix - If true, interpret paths in POSIX format (e.g. on Windows)
|
|
319
|
+
* @returns `true` if `originalPath` is under `root`
|
|
320
|
+
* @throws {Error} If either path is not absolute
|
|
319
321
|
*/
|
|
320
322
|
function isSubPath(originalPath, root, forcePosix = null) {
|
|
321
|
-
const pathObj = forcePosix ?
|
|
323
|
+
const pathObj = forcePosix ? node_path_1.default.posix : node_path_1.default;
|
|
322
324
|
for (const p of [originalPath, root]) {
|
|
323
325
|
if (!pathObj.isAbsolute(p)) {
|
|
324
326
|
throw new Error(`'${p}' is expected to be an absolute path`);
|
|
@@ -329,41 +331,27 @@ function isSubPath(originalPath, root, forcePosix = null) {
|
|
|
329
331
|
return normalizedPath.startsWith(normalizedRoot);
|
|
330
332
|
}
|
|
331
333
|
/**
|
|
332
|
-
* Checks whether the given paths
|
|
333
|
-
*
|
|
334
|
+
* Checks whether the given paths refer to the same file system entity (same inode).
|
|
335
|
+
* All paths must exist.
|
|
334
336
|
*
|
|
335
|
-
* @param
|
|
336
|
-
* @param
|
|
337
|
-
* @param
|
|
338
|
-
* @returns
|
|
337
|
+
* @param path1 - First path
|
|
338
|
+
* @param path2 - Second path
|
|
339
|
+
* @param pathN - Additional paths to compare
|
|
340
|
+
* @returns `true` if all paths resolve to the same file/directory
|
|
339
341
|
*/
|
|
340
342
|
async function isSameDestination(path1, path2, ...pathN) {
|
|
341
343
|
const allPaths = [path1, path2, ...pathN];
|
|
342
|
-
if (!(await
|
|
344
|
+
if (!(await (0, asyncbox_1.asyncmap)(allPaths, async (p) => fs_1.fs.exists(p))).every(Boolean)) {
|
|
343
345
|
return false;
|
|
344
346
|
}
|
|
345
347
|
const areAllItemsEqual = (arr) => !!arr.reduce((a, b) => (a === b ? a : NaN));
|
|
346
348
|
if (areAllItemsEqual(allPaths)) {
|
|
347
349
|
return true;
|
|
348
350
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
})).ino;
|
|
352
|
-
return areAllItemsEqual(await bluebird_1.default.map(allPaths, mapCb));
|
|
351
|
+
const mapCb = async (x) => (await fs_1.fs.stat(x, { bigint: true })).ino;
|
|
352
|
+
return areAllItemsEqual(await (0, asyncbox_1.asyncmap)(allPaths, mapCb));
|
|
353
353
|
}
|
|
354
|
-
|
|
355
|
-
* Coerces the given number/string to a valid version string
|
|
356
|
-
*
|
|
357
|
-
* @template {boolean} [Strict=true]
|
|
358
|
-
* @param {string} ver - Version string to coerce
|
|
359
|
-
* @param {Strict} [strict] - If `true` then an exception will be thrown
|
|
360
|
-
* if `ver` cannot be coerced
|
|
361
|
-
* @returns {Strict extends true ? string : string|null} Coerced version number or null if the string cannot be
|
|
362
|
-
* coerced and strict mode is disabled
|
|
363
|
-
* @throws {Error} if strict mode is enabled and `ver` cannot be coerced
|
|
364
|
-
*/
|
|
365
|
-
function coerceVersion(ver, strict = /** @type {Strict} */ (true)) {
|
|
366
|
-
// First try to parse as-is, then coerce if needed
|
|
354
|
+
function coerceVersion(ver, strict = true) {
|
|
367
355
|
let result = semver.valid(`${ver}`);
|
|
368
356
|
if (!result) {
|
|
369
357
|
result = semver.valid(semver.coerce(`${ver}`));
|
|
@@ -371,21 +359,17 @@ function coerceVersion(ver, strict = /** @type {Strict} */ (true)) {
|
|
|
371
359
|
if (strict && !result) {
|
|
372
360
|
throw new Error(`'${ver}' cannot be coerced to a valid version number`);
|
|
373
361
|
}
|
|
374
|
-
return
|
|
362
|
+
return result;
|
|
375
363
|
}
|
|
376
364
|
const SUPPORTED_OPERATORS = ['==', '!=', '>', '<', '>=', '<=', '='];
|
|
377
365
|
/**
|
|
378
|
-
* Compares two version strings
|
|
366
|
+
* Compares two version strings using the given operator.
|
|
379
367
|
*
|
|
380
|
-
* @param
|
|
381
|
-
*
|
|
382
|
-
* @param
|
|
383
|
-
*
|
|
384
|
-
* @
|
|
385
|
-
* ==, !=, >, <, <=, >=, =
|
|
386
|
-
* @returns {boolean} true or false depending on the actual comparison result
|
|
387
|
-
* @throws {Error} if an unsupported operator is supplied or any of the supplied
|
|
388
|
-
* version strings cannot be coerced
|
|
368
|
+
* @param ver1 - First version string
|
|
369
|
+
* @param operator - One of: ==, !=, >, <, >=, <=, =
|
|
370
|
+
* @param ver2 - Second version string
|
|
371
|
+
* @returns `true` if ver1 operator ver2 holds (e.g. "2.0.0" >= "1.0.0")
|
|
372
|
+
* @throws {Error} If operator is unsupported or either version cannot be coerced
|
|
389
373
|
*/
|
|
390
374
|
function compareVersions(ver1, operator, ver2) {
|
|
391
375
|
if (!SUPPORTED_OPERATORS.includes(operator)) {
|
|
@@ -393,170 +377,131 @@ function compareVersions(ver1, operator, ver2) {
|
|
|
393
377
|
`Only '${JSON.stringify(SUPPORTED_OPERATORS)}' operators are supported`);
|
|
394
378
|
}
|
|
395
379
|
const semverOperator = ['==', '!='].includes(operator) ? '=' : operator;
|
|
396
|
-
const
|
|
380
|
+
const v1 = coerceVersion(ver1, true);
|
|
381
|
+
const v2 = coerceVersion(ver2, true);
|
|
382
|
+
const result = semver.satisfies(v1, `${semverOperator}${v2}`);
|
|
397
383
|
return operator === '!=' ? !result : result;
|
|
398
384
|
}
|
|
399
385
|
/**
|
|
400
|
-
*
|
|
401
|
-
* for more details
|
|
386
|
+
* Quotes and escapes command-line arguments so they can be safely passed to a shell.
|
|
402
387
|
*
|
|
403
|
-
* @param
|
|
404
|
-
* @returns
|
|
388
|
+
* @param args - Single argument or array of arguments to quote
|
|
389
|
+
* @returns Quoted string suitable for shell parsing
|
|
405
390
|
*/
|
|
406
391
|
function quote(args) {
|
|
407
392
|
return (0, shell_quote_1.quote)(lodash_1.default.castArray(args));
|
|
408
393
|
}
|
|
409
394
|
/**
|
|
410
|
-
*
|
|
411
|
-
* @property {boolean} [inclusive=false] - Whether to prefix with the number (e.g., 3 ducks)
|
|
412
|
-
*/
|
|
413
|
-
/**
|
|
414
|
-
* Get the form of a word appropriate to the count
|
|
395
|
+
* Returns the plural or singular form of a word appropriate to the count (e.g. "duck" + 1 → "duck", + 2 → "ducks").
|
|
415
396
|
*
|
|
416
|
-
* @param
|
|
417
|
-
* @param
|
|
418
|
-
* @param
|
|
419
|
-
*
|
|
420
|
-
* @returns {string} The word pluralized according to the number
|
|
397
|
+
* @param word - The word to pluralize (or singularize when count is 1)
|
|
398
|
+
* @param count - The count used to choose singular vs plural
|
|
399
|
+
* @param options - Options object or boolean: use `inclusive: true` (or `true`) to prefix with the number (e.g. "3 ducks")
|
|
400
|
+
* @returns The correctly inflected word, optionally prefixed with the count
|
|
421
401
|
*/
|
|
422
402
|
function pluralize(word, count, options = {}) {
|
|
423
403
|
let inclusive = false;
|
|
424
404
|
if (lodash_1.default.isBoolean(options)) {
|
|
425
|
-
// if passed in as a boolean
|
|
426
405
|
inclusive = options;
|
|
427
406
|
}
|
|
428
407
|
else if (lodash_1.default.isBoolean(options?.inclusive)) {
|
|
429
|
-
// if passed in as an options hash
|
|
430
408
|
inclusive = options.inclusive;
|
|
431
409
|
}
|
|
432
410
|
return (0, pluralize_1.default)(word, count, inclusive);
|
|
433
411
|
}
|
|
434
412
|
/**
|
|
435
|
-
*
|
|
436
|
-
* @property {number} [maxSize=1073741824] The maximum size of
|
|
437
|
-
* the resulting buffer in bytes. This is set to 1GB by default, because
|
|
438
|
-
* Appium limits the maximum HTTP body size to 1GB. Also, the NodeJS heap
|
|
439
|
-
* size must be enough to keep the resulting object (usually this size is
|
|
440
|
-
* limited to 1.4 GB)
|
|
441
|
-
*/
|
|
442
|
-
/**
|
|
443
|
-
* Converts contents of a local file to an in-memory base-64 encoded buffer.
|
|
444
|
-
* The operation is memory-usage friendly and should be used while encoding
|
|
445
|
-
* large files to base64
|
|
413
|
+
* Reads a file and returns its contents as a base64-encoded buffer.
|
|
446
414
|
*
|
|
447
|
-
* @param
|
|
448
|
-
* @param
|
|
449
|
-
* @returns
|
|
450
|
-
* @throws {Error}
|
|
451
|
-
* or the source file is too
|
|
415
|
+
* @param srcPath - Full path to the file to encode
|
|
416
|
+
* @param opts - Encoding options (e.g. maxSize to cap buffer size)
|
|
417
|
+
* @returns Buffer containing the base64-encoded file content
|
|
418
|
+
* @throws {Error} If the file does not exist, is a directory, cannot be read, or exceeds maxSize
|
|
452
419
|
*/
|
|
453
420
|
async function toInMemoryBase64(srcPath, opts = {}) {
|
|
454
421
|
if (!(await fs_1.fs.exists(srcPath)) || (await fs_1.fs.stat(srcPath)).isDirectory()) {
|
|
455
422
|
throw new Error(`No such file: ${srcPath}`);
|
|
456
423
|
}
|
|
457
|
-
const { maxSize = 1 * GiB } = opts;
|
|
424
|
+
const { maxSize = 1 * exports.GiB } = opts;
|
|
458
425
|
const resultBuffers = [];
|
|
459
426
|
let resultBuffersSize = 0;
|
|
460
|
-
const resultWriteStream = new
|
|
461
|
-
write
|
|
427
|
+
const resultWriteStream = new node_stream_1.default.Writable({
|
|
428
|
+
write(buffer, _encoding, next) {
|
|
462
429
|
resultBuffers.push(buffer);
|
|
463
430
|
resultBuffersSize += buffer.length;
|
|
464
431
|
if (maxSize > 0 && resultBuffersSize > maxSize) {
|
|
465
|
-
resultWriteStream.emit('error', new Error(`The size of the resulting `
|
|
466
|
-
`buffer must not be greater than ${toReadableSizeString(maxSize)}`));
|
|
432
|
+
resultWriteStream.emit('error', new Error(`The size of the resulting buffer must not be greater than ${toReadableSizeString(maxSize)}`));
|
|
467
433
|
}
|
|
468
434
|
next();
|
|
469
435
|
},
|
|
470
436
|
});
|
|
471
437
|
const readerStream = fs_1.fs.createReadStream(srcPath);
|
|
472
438
|
const base64EncoderStream = new base64_stream_1.Base64Encode();
|
|
473
|
-
const
|
|
439
|
+
const encoderWritable = base64EncoderStream;
|
|
440
|
+
const encoderReadable = base64EncoderStream;
|
|
441
|
+
const resultWriteStreamPromise = new Promise((resolve, reject) => {
|
|
474
442
|
resultWriteStream.once('error', (e) => {
|
|
475
|
-
readerStream.unpipe(
|
|
476
|
-
|
|
443
|
+
readerStream.unpipe(encoderWritable);
|
|
444
|
+
encoderReadable.unpipe(resultWriteStream);
|
|
477
445
|
readerStream.destroy();
|
|
478
446
|
reject(e);
|
|
479
447
|
});
|
|
480
|
-
resultWriteStream.once('finish', resolve);
|
|
448
|
+
resultWriteStream.once('finish', () => resolve());
|
|
481
449
|
});
|
|
482
|
-
const readStreamPromise = new
|
|
483
|
-
readerStream.once('close', resolve);
|
|
450
|
+
const readStreamPromise = new Promise((resolve, reject) => {
|
|
451
|
+
readerStream.once('close', () => resolve());
|
|
484
452
|
readerStream.once('error', (e) => reject(new Error(`Failed to read '${srcPath}': ${e.message}`)));
|
|
485
453
|
});
|
|
486
|
-
readerStream.pipe(
|
|
487
|
-
|
|
488
|
-
await
|
|
454
|
+
readerStream.pipe(encoderWritable);
|
|
455
|
+
encoderReadable.pipe(resultWriteStream);
|
|
456
|
+
await Promise.all([readStreamPromise, resultWriteStreamPromise]);
|
|
489
457
|
return Buffer.concat(resultBuffers);
|
|
490
458
|
}
|
|
491
459
|
/**
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
* the first attempt to acquire it timed out.
|
|
496
|
-
*/
|
|
497
|
-
/**
|
|
498
|
-
* Create an async function which, when called, will not proceed until a certain file is no
|
|
499
|
-
* longer present on the system. This allows for preventing concurrent behavior across processes
|
|
500
|
-
* using a known lockfile path.
|
|
460
|
+
* Creates a guard that serializes access to a critical section using a lock file.
|
|
461
|
+
* The returned function acquires the lock, runs the given behavior, then releases the lock.
|
|
462
|
+
* Also exposes `.check()` to test whether the lock is currently held.
|
|
501
463
|
*
|
|
502
|
-
* @
|
|
503
|
-
* @param
|
|
504
|
-
* @
|
|
505
|
-
* @returns async function that takes another async function defining the locked
|
|
506
|
-
* behavior
|
|
464
|
+
* @param lockFile - Full path to the lock file
|
|
465
|
+
* @param opts - Options (see {@link LockFileOptions})
|
|
466
|
+
* @returns Async function that accepts a callback to run under the lock, plus a `.check()` method
|
|
507
467
|
*/
|
|
508
468
|
function getLockFileGuard(lockFile, opts = {}) {
|
|
509
469
|
const { timeout = 120, tryRecovery = false } = opts;
|
|
510
|
-
const lock =
|
|
511
|
-
const
|
|
512
|
-
const unlock =
|
|
513
|
-
|
|
514
|
-
* @param {(...args: any[]) => T} behavior
|
|
515
|
-
* @returns {Promise<T>}
|
|
516
|
-
*/
|
|
517
|
-
const guard = async (behavior) => {
|
|
470
|
+
const lock = (0, node_util_1.promisify)(_lockfile.lock);
|
|
471
|
+
const checkLock = (0, node_util_1.promisify)(_lockfile.check);
|
|
472
|
+
const unlock = (0, node_util_1.promisify)(_lockfile.unlock);
|
|
473
|
+
const guard = Object.assign(async (behavior) => {
|
|
518
474
|
let triedRecovery = false;
|
|
519
|
-
|
|
475
|
+
let acquired = false;
|
|
476
|
+
while (!acquired) {
|
|
520
477
|
try {
|
|
521
|
-
// if the lockfile doesn't exist, lock it synchronously to make sure no other call
|
|
522
|
-
// on the same spin of the event loop can also initiate a lock. If the lockfile does exist
|
|
523
|
-
// then just use the regular async 'lock' method which will wait on the lock.
|
|
524
478
|
if (_lockfile.checkSync(lockFile)) {
|
|
525
479
|
await lock(lockFile, { wait: timeout * 1000 });
|
|
526
480
|
}
|
|
527
481
|
else {
|
|
528
482
|
_lockfile.lockSync(lockFile);
|
|
529
483
|
}
|
|
530
|
-
|
|
484
|
+
acquired = true;
|
|
531
485
|
}
|
|
532
486
|
catch (e) {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
// without a chance to clean up pending locks: https://github.com/npm/lockfile/issues/26
|
|
487
|
+
const err = e;
|
|
488
|
+
if (lodash_1.default.includes(err.message, 'EEXIST') && tryRecovery && !triedRecovery) {
|
|
536
489
|
_lockfile.unlockSync(lockFile);
|
|
537
490
|
triedRecovery = true;
|
|
538
|
-
continue;
|
|
539
491
|
}
|
|
540
|
-
|
|
541
|
-
`
|
|
492
|
+
else {
|
|
493
|
+
throw new Error(`Could not acquire lock on '${lockFile}' after ${timeout}s. ` +
|
|
494
|
+
`Original error: ${err.message}`);
|
|
495
|
+
}
|
|
542
496
|
}
|
|
543
|
-
|
|
544
|
-
} while (true);
|
|
497
|
+
}
|
|
545
498
|
try {
|
|
546
499
|
return await behavior();
|
|
547
500
|
}
|
|
548
501
|
finally {
|
|
549
|
-
// whether the behavior succeeded or not, get rid of the lock
|
|
550
502
|
await unlock(lockFile);
|
|
551
503
|
}
|
|
552
|
-
};
|
|
553
|
-
guard.check = async () => await check(lockFile);
|
|
504
|
+
}, { check: () => checkLock(lockFile) });
|
|
554
505
|
return guard;
|
|
555
506
|
}
|
|
556
|
-
/**
|
|
557
|
-
* A `string` which is never `''`.
|
|
558
|
-
*
|
|
559
|
-
* @template {string} T
|
|
560
|
-
* @typedef {T extends '' ? never : T} NonEmptyString
|
|
561
|
-
*/
|
|
562
507
|
//# sourceMappingURL=util.js.map
|