@appium/support 7.0.5 → 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/LICENSE +201 -0
- package/build/lib/console.d.ts +42 -88
- package/build/lib/console.d.ts.map +1 -1
- package/build/lib/console.js +20 -80
- 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 +13 -50
- 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 +88 -188
- 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 +53 -76
- 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 +106 -111
- 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 +59 -117
- 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 +46 -11
- 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 +41 -73
- 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 +193 -247
- 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 +210 -258
- 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} +31 -59
- 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} +134 -133
- 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} +341 -296
- package/package.json +20 -22
- 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 -584
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,16 +45,16 @@ 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;
|
|
@@ -62,160 +62,162 @@ const bluebird_1 = __importDefault(require("bluebird"));
|
|
|
62
62
|
const lodash_1 = __importDefault(require("lodash"));
|
|
63
63
|
const node_os_1 = __importDefault(require("node:os"));
|
|
64
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 node_stream_1 = __importDefault(require("node: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
183
|
reject(new bluebird_1.default.CancellationError());
|
|
182
184
|
};
|
|
183
185
|
return delay;
|
|
184
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
|
+
*/
|
|
185
194
|
function multiResolve(roots, ...args) {
|
|
186
195
|
return roots.map((root) => node_path_1.default.resolve(root, ...args));
|
|
187
196
|
}
|
|
188
197
|
/**
|
|
189
|
-
* Parses
|
|
198
|
+
* Parses a value as JSON if it is a string; otherwise returns the value as-is.
|
|
190
199
|
*
|
|
191
|
-
* @param
|
|
192
|
-
* @returns
|
|
200
|
+
* @param obj - String (to parse) or other value (returned unchanged)
|
|
201
|
+
* @returns Parsed object or original value
|
|
193
202
|
*/
|
|
194
203
|
function safeJsonParse(obj) {
|
|
195
204
|
try {
|
|
196
205
|
return JSON.parse(obj);
|
|
197
206
|
}
|
|
198
207
|
catch {
|
|
199
|
-
// ignore: this is not json parsable
|
|
200
208
|
return obj;
|
|
201
209
|
}
|
|
202
210
|
}
|
|
203
211
|
/**
|
|
204
|
-
* Stringifies
|
|
205
|
-
* display. This mimics JSON.stringify (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)
|
|
206
|
-
* except the `replacer` argument can only be a function.
|
|
212
|
+
* Stringifies an object to JSON, converting Buffers to strings for readable output.
|
|
207
213
|
*
|
|
208
|
-
* @param
|
|
209
|
-
* @param
|
|
210
|
-
*
|
|
211
|
-
* @
|
|
212
|
-
* string for readability purposes. Defaults to 2
|
|
213
|
-
* @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
|
|
214
218
|
*/
|
|
215
219
|
function jsonStringify(obj, replacer = null, space = 2) {
|
|
216
|
-
|
|
217
|
-
const replacerFunc = lodash_1.default.isFunction(replacer) ? replacer : (k, v) => v;
|
|
218
|
-
// Buffers cannot be serialized in a readable way
|
|
220
|
+
const replacerFunc = lodash_1.default.isFunction(replacer) ? replacer : (_k, v) => v;
|
|
219
221
|
const bufferToJSON = Buffer.prototype.toJSON;
|
|
220
222
|
delete Buffer.prototype.toJSON;
|
|
221
223
|
try {
|
|
@@ -225,96 +227,97 @@ function jsonStringify(obj, replacer = null, space = 2) {
|
|
|
225
227
|
}, space);
|
|
226
228
|
}
|
|
227
229
|
finally {
|
|
228
|
-
// restore the function, so as to not break further serialization
|
|
229
230
|
Buffer.prototype.toJSON = bufferToJSON;
|
|
230
231
|
}
|
|
231
232
|
}
|
|
232
233
|
/**
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* @
|
|
237
|
-
* @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
|
|
238
238
|
*/
|
|
239
239
|
function unwrapElement(el) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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];
|
|
243
244
|
}
|
|
244
245
|
}
|
|
245
|
-
return
|
|
246
|
+
return el;
|
|
246
247
|
}
|
|
247
248
|
/**
|
|
249
|
+
* Wraps an element ID string in an element object compatible with both W3C and JSONWP.
|
|
248
250
|
*
|
|
249
|
-
* @param
|
|
250
|
-
* @returns
|
|
251
|
+
* @param elementId - The element ID to wrap
|
|
252
|
+
* @returns Element object with both ELEMENT and W3C identifier keys
|
|
251
253
|
*/
|
|
252
254
|
function wrapElement(elementId) {
|
|
253
255
|
return {
|
|
254
256
|
ELEMENT: elementId,
|
|
255
|
-
[W3C_WEB_ELEMENT_IDENTIFIER]: elementId,
|
|
257
|
+
[exports.W3C_WEB_ELEMENT_IDENTIFIER]: elementId,
|
|
256
258
|
};
|
|
257
259
|
}
|
|
258
|
-
|
|
259
|
-
* Returns
|
|
260
|
-
*
|
|
261
|
-
* If the predicate is
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
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
|
|
265
269
|
*/
|
|
266
270
|
function filterObject(obj, predicate) {
|
|
267
|
-
|
|
271
|
+
const newObj = lodash_1.default.clone(obj);
|
|
272
|
+
let pred;
|
|
268
273
|
if (lodash_1.default.isUndefined(predicate)) {
|
|
269
|
-
|
|
270
|
-
predicate = (v) => !lodash_1.default.isUndefined(v);
|
|
274
|
+
pred = (v) => !lodash_1.default.isUndefined(v);
|
|
271
275
|
}
|
|
272
276
|
else if (!lodash_1.default.isFunction(predicate)) {
|
|
273
|
-
// make predicate into a function
|
|
274
277
|
const valuePredicate = predicate;
|
|
275
|
-
|
|
278
|
+
pred = (v) => v === valuePredicate;
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
pred = predicate;
|
|
276
282
|
}
|
|
277
283
|
for (const key of Object.keys(obj)) {
|
|
278
|
-
if (!
|
|
284
|
+
if (!pred(obj[key], obj)) {
|
|
279
285
|
delete newObj[key];
|
|
280
286
|
}
|
|
281
287
|
}
|
|
282
288
|
return newObj;
|
|
283
289
|
}
|
|
284
290
|
/**
|
|
285
|
-
* Converts
|
|
291
|
+
* Converts a byte count to a human-readable size string (e.g. "1.50 MB").
|
|
286
292
|
*
|
|
287
|
-
* @param
|
|
288
|
-
* @returns
|
|
289
|
-
*
|
|
290
|
-
* @throws {Error} If bytes count cannot be converted to an integer or
|
|
291
|
-
* 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
|
|
292
296
|
*/
|
|
293
297
|
function toReadableSizeString(bytes) {
|
|
294
298
|
const intBytes = parseInt(String(bytes), 10);
|
|
295
299
|
if (isNaN(intBytes) || intBytes < 0) {
|
|
296
300
|
throw new Error(`Cannot convert '${bytes}' to a readable size format`);
|
|
297
301
|
}
|
|
298
|
-
if (intBytes >= GiB) {
|
|
299
|
-
return `${(intBytes / (GiB * 1.0)).toFixed(2)} GB`;
|
|
302
|
+
if (intBytes >= exports.GiB) {
|
|
303
|
+
return `${(intBytes / (exports.GiB * 1.0)).toFixed(2)} GB`;
|
|
300
304
|
}
|
|
301
|
-
else if (intBytes >= MiB) {
|
|
302
|
-
return `${(intBytes / (MiB * 1.0)).toFixed(2)} MB`;
|
|
305
|
+
else if (intBytes >= exports.MiB) {
|
|
306
|
+
return `${(intBytes / (exports.MiB * 1.0)).toFixed(2)} MB`;
|
|
303
307
|
}
|
|
304
|
-
else if (intBytes >= KiB) {
|
|
305
|
-
return `${(intBytes / (KiB * 1.0)).toFixed(2)} KB`;
|
|
308
|
+
else if (intBytes >= exports.KiB) {
|
|
309
|
+
return `${(intBytes / (exports.KiB * 1.0)).toFixed(2)} KB`;
|
|
306
310
|
}
|
|
307
311
|
return `${intBytes} B`;
|
|
308
312
|
}
|
|
309
313
|
/**
|
|
310
|
-
* Checks whether the given path is a subpath of the
|
|
311
|
-
* particular root folder. Both paths can include .. and . specifiers
|
|
314
|
+
* Checks whether the given path is a subpath of the given root folder.
|
|
312
315
|
*
|
|
313
|
-
* @param
|
|
314
|
-
* @param
|
|
315
|
-
* @param
|
|
316
|
-
* @returns
|
|
317
|
-
* @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
|
|
318
321
|
*/
|
|
319
322
|
function isSubPath(originalPath, root, forcePosix = null) {
|
|
320
323
|
const pathObj = forcePosix ? node_path_1.default.posix : node_path_1.default;
|
|
@@ -328,41 +331,27 @@ function isSubPath(originalPath, root, forcePosix = null) {
|
|
|
328
331
|
return normalizedPath.startsWith(normalizedRoot);
|
|
329
332
|
}
|
|
330
333
|
/**
|
|
331
|
-
* Checks whether the given paths
|
|
332
|
-
*
|
|
334
|
+
* Checks whether the given paths refer to the same file system entity (same inode).
|
|
335
|
+
* All paths must exist.
|
|
333
336
|
*
|
|
334
|
-
* @param
|
|
335
|
-
* @param
|
|
336
|
-
* @param
|
|
337
|
-
* @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
|
|
338
341
|
*/
|
|
339
342
|
async function isSameDestination(path1, path2, ...pathN) {
|
|
340
343
|
const allPaths = [path1, path2, ...pathN];
|
|
341
|
-
if (!(await
|
|
344
|
+
if (!(await (0, asyncbox_1.asyncmap)(allPaths, async (p) => fs_1.fs.exists(p))).every(Boolean)) {
|
|
342
345
|
return false;
|
|
343
346
|
}
|
|
344
347
|
const areAllItemsEqual = (arr) => !!arr.reduce((a, b) => (a === b ? a : NaN));
|
|
345
348
|
if (areAllItemsEqual(allPaths)) {
|
|
346
349
|
return true;
|
|
347
350
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
})).ino;
|
|
351
|
-
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));
|
|
352
353
|
}
|
|
353
|
-
|
|
354
|
-
* Coerces the given number/string to a valid version string
|
|
355
|
-
*
|
|
356
|
-
* @template {boolean} [Strict=true]
|
|
357
|
-
* @param {string} ver - Version string to coerce
|
|
358
|
-
* @param {Strict} [strict] - If `true` then an exception will be thrown
|
|
359
|
-
* if `ver` cannot be coerced
|
|
360
|
-
* @returns {Strict extends true ? string : string|null} Coerced version number or null if the string cannot be
|
|
361
|
-
* coerced and strict mode is disabled
|
|
362
|
-
* @throws {Error} if strict mode is enabled and `ver` cannot be coerced
|
|
363
|
-
*/
|
|
364
|
-
function coerceVersion(ver, strict = /** @type {Strict} */ (true)) {
|
|
365
|
-
// First try to parse as-is, then coerce if needed
|
|
354
|
+
function coerceVersion(ver, strict = true) {
|
|
366
355
|
let result = semver.valid(`${ver}`);
|
|
367
356
|
if (!result) {
|
|
368
357
|
result = semver.valid(semver.coerce(`${ver}`));
|
|
@@ -370,21 +359,17 @@ function coerceVersion(ver, strict = /** @type {Strict} */ (true)) {
|
|
|
370
359
|
if (strict && !result) {
|
|
371
360
|
throw new Error(`'${ver}' cannot be coerced to a valid version number`);
|
|
372
361
|
}
|
|
373
|
-
return
|
|
362
|
+
return result;
|
|
374
363
|
}
|
|
375
364
|
const SUPPORTED_OPERATORS = ['==', '!=', '>', '<', '>=', '<=', '='];
|
|
376
365
|
/**
|
|
377
|
-
* Compares two version strings
|
|
366
|
+
* Compares two version strings using the given operator.
|
|
378
367
|
*
|
|
379
|
-
* @param
|
|
380
|
-
*
|
|
381
|
-
* @param
|
|
382
|
-
*
|
|
383
|
-
* @
|
|
384
|
-
* ==, !=, >, <, <=, >=, =
|
|
385
|
-
* @returns {boolean} true or false depending on the actual comparison result
|
|
386
|
-
* @throws {Error} if an unsupported operator is supplied or any of the supplied
|
|
387
|
-
* 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
|
|
388
373
|
*/
|
|
389
374
|
function compareVersions(ver1, operator, ver2) {
|
|
390
375
|
if (!SUPPORTED_OPERATORS.includes(operator)) {
|
|
@@ -392,170 +377,131 @@ function compareVersions(ver1, operator, ver2) {
|
|
|
392
377
|
`Only '${JSON.stringify(SUPPORTED_OPERATORS)}' operators are supported`);
|
|
393
378
|
}
|
|
394
379
|
const semverOperator = ['==', '!='].includes(operator) ? '=' : operator;
|
|
395
|
-
const
|
|
380
|
+
const v1 = coerceVersion(ver1, true);
|
|
381
|
+
const v2 = coerceVersion(ver2, true);
|
|
382
|
+
const result = semver.satisfies(v1, `${semverOperator}${v2}`);
|
|
396
383
|
return operator === '!=' ? !result : result;
|
|
397
384
|
}
|
|
398
385
|
/**
|
|
399
|
-
*
|
|
400
|
-
* for more details
|
|
386
|
+
* Quotes and escapes command-line arguments so they can be safely passed to a shell.
|
|
401
387
|
*
|
|
402
|
-
* @param
|
|
403
|
-
* @returns
|
|
388
|
+
* @param args - Single argument or array of arguments to quote
|
|
389
|
+
* @returns Quoted string suitable for shell parsing
|
|
404
390
|
*/
|
|
405
391
|
function quote(args) {
|
|
406
392
|
return (0, shell_quote_1.quote)(lodash_1.default.castArray(args));
|
|
407
393
|
}
|
|
408
394
|
/**
|
|
409
|
-
*
|
|
410
|
-
* @property {boolean} [inclusive=false] - Whether to prefix with the number (e.g., 3 ducks)
|
|
411
|
-
*/
|
|
412
|
-
/**
|
|
413
|
-
* 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").
|
|
414
396
|
*
|
|
415
|
-
* @param
|
|
416
|
-
* @param
|
|
417
|
-
* @param
|
|
418
|
-
*
|
|
419
|
-
* @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
|
|
420
401
|
*/
|
|
421
402
|
function pluralize(word, count, options = {}) {
|
|
422
403
|
let inclusive = false;
|
|
423
404
|
if (lodash_1.default.isBoolean(options)) {
|
|
424
|
-
// if passed in as a boolean
|
|
425
405
|
inclusive = options;
|
|
426
406
|
}
|
|
427
407
|
else if (lodash_1.default.isBoolean(options?.inclusive)) {
|
|
428
|
-
// if passed in as an options hash
|
|
429
408
|
inclusive = options.inclusive;
|
|
430
409
|
}
|
|
431
410
|
return (0, pluralize_1.default)(word, count, inclusive);
|
|
432
411
|
}
|
|
433
412
|
/**
|
|
434
|
-
*
|
|
435
|
-
* @property {number} [maxSize=1073741824] The maximum size of
|
|
436
|
-
* the resulting buffer in bytes. This is set to 1GB by default, because
|
|
437
|
-
* Appium limits the maximum HTTP body size to 1GB. Also, the NodeJS heap
|
|
438
|
-
* size must be enough to keep the resulting object (usually this size is
|
|
439
|
-
* limited to 1.4 GB)
|
|
440
|
-
*/
|
|
441
|
-
/**
|
|
442
|
-
* Converts contents of a local file to an in-memory base-64 encoded buffer.
|
|
443
|
-
* The operation is memory-usage friendly and should be used while encoding
|
|
444
|
-
* large files to base64
|
|
413
|
+
* Reads a file and returns its contents as a base64-encoded buffer.
|
|
445
414
|
*
|
|
446
|
-
* @param
|
|
447
|
-
* @param
|
|
448
|
-
* @returns
|
|
449
|
-
* @throws {Error}
|
|
450
|
-
* 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
|
|
451
419
|
*/
|
|
452
420
|
async function toInMemoryBase64(srcPath, opts = {}) {
|
|
453
421
|
if (!(await fs_1.fs.exists(srcPath)) || (await fs_1.fs.stat(srcPath)).isDirectory()) {
|
|
454
422
|
throw new Error(`No such file: ${srcPath}`);
|
|
455
423
|
}
|
|
456
|
-
const { maxSize = 1 * GiB } = opts;
|
|
424
|
+
const { maxSize = 1 * exports.GiB } = opts;
|
|
457
425
|
const resultBuffers = [];
|
|
458
426
|
let resultBuffersSize = 0;
|
|
459
427
|
const resultWriteStream = new node_stream_1.default.Writable({
|
|
460
|
-
write
|
|
428
|
+
write(buffer, _encoding, next) {
|
|
461
429
|
resultBuffers.push(buffer);
|
|
462
430
|
resultBuffersSize += buffer.length;
|
|
463
431
|
if (maxSize > 0 && resultBuffersSize > maxSize) {
|
|
464
|
-
resultWriteStream.emit('error', new Error(`The size of the resulting `
|
|
465
|
-
`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)}`));
|
|
466
433
|
}
|
|
467
434
|
next();
|
|
468
435
|
},
|
|
469
436
|
});
|
|
470
437
|
const readerStream = fs_1.fs.createReadStream(srcPath);
|
|
471
438
|
const base64EncoderStream = new base64_stream_1.Base64Encode();
|
|
472
|
-
const
|
|
439
|
+
const encoderWritable = base64EncoderStream;
|
|
440
|
+
const encoderReadable = base64EncoderStream;
|
|
441
|
+
const resultWriteStreamPromise = new Promise((resolve, reject) => {
|
|
473
442
|
resultWriteStream.once('error', (e) => {
|
|
474
|
-
readerStream.unpipe(
|
|
475
|
-
|
|
443
|
+
readerStream.unpipe(encoderWritable);
|
|
444
|
+
encoderReadable.unpipe(resultWriteStream);
|
|
476
445
|
readerStream.destroy();
|
|
477
446
|
reject(e);
|
|
478
447
|
});
|
|
479
|
-
resultWriteStream.once('finish', resolve);
|
|
448
|
+
resultWriteStream.once('finish', () => resolve());
|
|
480
449
|
});
|
|
481
|
-
const readStreamPromise = new
|
|
482
|
-
readerStream.once('close', resolve);
|
|
450
|
+
const readStreamPromise = new Promise((resolve, reject) => {
|
|
451
|
+
readerStream.once('close', () => resolve());
|
|
483
452
|
readerStream.once('error', (e) => reject(new Error(`Failed to read '${srcPath}': ${e.message}`)));
|
|
484
453
|
});
|
|
485
|
-
readerStream.pipe(
|
|
486
|
-
|
|
487
|
-
await
|
|
454
|
+
readerStream.pipe(encoderWritable);
|
|
455
|
+
encoderReadable.pipe(resultWriteStream);
|
|
456
|
+
await Promise.all([readStreamPromise, resultWriteStreamPromise]);
|
|
488
457
|
return Buffer.concat(resultBuffers);
|
|
489
458
|
}
|
|
490
459
|
/**
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
* the first attempt to acquire it timed out.
|
|
495
|
-
*/
|
|
496
|
-
/**
|
|
497
|
-
* Create an async function which, when called, will not proceed until a certain file is no
|
|
498
|
-
* longer present on the system. This allows for preventing concurrent behavior across processes
|
|
499
|
-
* 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.
|
|
500
463
|
*
|
|
501
|
-
* @
|
|
502
|
-
* @param
|
|
503
|
-
* @
|
|
504
|
-
* @returns async function that takes another async function defining the locked
|
|
505
|
-
* 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
|
|
506
467
|
*/
|
|
507
468
|
function getLockFileGuard(lockFile, opts = {}) {
|
|
508
469
|
const { timeout = 120, tryRecovery = false } = opts;
|
|
509
|
-
const lock =
|
|
510
|
-
const
|
|
511
|
-
const unlock =
|
|
512
|
-
|
|
513
|
-
* @param {(...args: any[]) => T} behavior
|
|
514
|
-
* @returns {Promise<T>}
|
|
515
|
-
*/
|
|
516
|
-
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) => {
|
|
517
474
|
let triedRecovery = false;
|
|
518
|
-
|
|
475
|
+
let acquired = false;
|
|
476
|
+
while (!acquired) {
|
|
519
477
|
try {
|
|
520
|
-
// if the lockfile doesn't exist, lock it synchronously to make sure no other call
|
|
521
|
-
// on the same spin of the event loop can also initiate a lock. If the lockfile does exist
|
|
522
|
-
// then just use the regular async 'lock' method which will wait on the lock.
|
|
523
478
|
if (_lockfile.checkSync(lockFile)) {
|
|
524
479
|
await lock(lockFile, { wait: timeout * 1000 });
|
|
525
480
|
}
|
|
526
481
|
else {
|
|
527
482
|
_lockfile.lockSync(lockFile);
|
|
528
483
|
}
|
|
529
|
-
|
|
484
|
+
acquired = true;
|
|
530
485
|
}
|
|
531
486
|
catch (e) {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
// 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) {
|
|
535
489
|
_lockfile.unlockSync(lockFile);
|
|
536
490
|
triedRecovery = true;
|
|
537
|
-
continue;
|
|
538
491
|
}
|
|
539
|
-
|
|
540
|
-
`
|
|
492
|
+
else {
|
|
493
|
+
throw new Error(`Could not acquire lock on '${lockFile}' after ${timeout}s. ` +
|
|
494
|
+
`Original error: ${err.message}`);
|
|
495
|
+
}
|
|
541
496
|
}
|
|
542
|
-
|
|
543
|
-
} while (true);
|
|
497
|
+
}
|
|
544
498
|
try {
|
|
545
499
|
return await behavior();
|
|
546
500
|
}
|
|
547
501
|
finally {
|
|
548
|
-
// whether the behavior succeeded or not, get rid of the lock
|
|
549
502
|
await unlock(lockFile);
|
|
550
503
|
}
|
|
551
|
-
};
|
|
552
|
-
guard.check = async () => await check(lockFile);
|
|
504
|
+
}, { check: () => checkLock(lockFile) });
|
|
553
505
|
return guard;
|
|
554
506
|
}
|
|
555
|
-
/**
|
|
556
|
-
* A `string` which is never `''`.
|
|
557
|
-
*
|
|
558
|
-
* @template {string} T
|
|
559
|
-
* @typedef {T extends '' ? never : T} NonEmptyString
|
|
560
|
-
*/
|
|
561
507
|
//# sourceMappingURL=util.js.map
|