@appium/support 2.55.4 → 2.56.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.
Files changed (54) hide show
  1. package/build/lib/env.js +102 -0
  2. package/build/lib/fs.js +74 -56
  3. package/build/lib/image-util.js +2 -4
  4. package/build/lib/index.js +18 -6
  5. package/build/lib/log-internal.js +2 -4
  6. package/build/lib/logger.js +2 -4
  7. package/build/lib/logging.js +2 -4
  8. package/build/lib/mjpeg.js +2 -4
  9. package/build/lib/mkdirp.js +7 -11
  10. package/build/lib/net.js +2 -4
  11. package/build/lib/node.js +99 -2
  12. package/build/lib/npm.js +240 -0
  13. package/build/lib/plist.js +2 -4
  14. package/build/lib/process.js +2 -4
  15. package/build/lib/system.js +2 -4
  16. package/build/lib/tempdir.js +2 -4
  17. package/build/lib/timing.js +2 -4
  18. package/build/lib/util.js +6 -8
  19. package/build/lib/zip.js +4 -8
  20. package/lib/env.js +162 -0
  21. package/lib/fs.js +193 -69
  22. package/lib/index.js +8 -2
  23. package/lib/log-internal.js +2 -2
  24. package/lib/logging.js +1 -1
  25. package/lib/mkdirp.js +3 -6
  26. package/lib/net.js +4 -4
  27. package/lib/node.js +104 -1
  28. package/lib/npm.js +335 -0
  29. package/lib/tempdir.js +6 -6
  30. package/lib/util.js +28 -24
  31. package/lib/zip.js +7 -8
  32. package/package.json +20 -10
  33. package/build/test/assets/sample_binary.plist +0 -0
  34. package/build/test/assets/sample_text.plist +0 -28
  35. package/build/test/fs-specs.js +0 -264
  36. package/build/test/helpers.js +0 -35
  37. package/build/test/image-util-e2e-specs.js +0 -78
  38. package/build/test/index-specs.js +0 -49
  39. package/build/test/log-internals-specs.js +0 -97
  40. package/build/test/logger/helpers.js +0 -71
  41. package/build/test/logger/logger-force-specs.js +0 -41
  42. package/build/test/logger/logger-normal-specs.js +0 -113
  43. package/build/test/logger/logger-test-specs.js +0 -40
  44. package/build/test/mjpeg-e2e-specs.js +0 -96
  45. package/build/test/net-e2e-specs.js +0 -32
  46. package/build/test/node-e2e-specs.js +0 -22
  47. package/build/test/plist-specs.js +0 -54
  48. package/build/test/process-specs.js +0 -104
  49. package/build/test/system-specs.js +0 -136
  50. package/build/test/tempdir-specs.js +0 -86
  51. package/build/test/timing-specs.js +0 -125
  52. package/build/test/util-e2e-specs.js +0 -136
  53. package/build/test/util-specs.js +0 -537
  54. package/build/test/zip-e2e-specs.js +0 -233
package/lib/npm.js ADDED
@@ -0,0 +1,335 @@
1
+ // @ts-check
2
+
3
+ import path from 'path';
4
+ import semver from 'semver';
5
+ import { exec } from 'teen_process';
6
+ import { fs } from './fs';
7
+ import * as util from './util';
8
+ import * as system from './system';
9
+ import resolveFrom from 'resolve-from';
10
+
11
+
12
+ /**
13
+ * Relative path to directory containing any Appium internal files
14
+ * XXX: this is duplicated in `appium/lib/constants.js`.
15
+ */
16
+ export const CACHE_DIR_RELATIVE_PATH = path.join(
17
+ 'node_modules',
18
+ '.cache',
19
+ 'appium',
20
+ );
21
+
22
+ /**
23
+ * Relative path to lockfile used when installing an extension via `appium`
24
+ */
25
+ export const INSTALL_LOCKFILE_RELATIVE_PATH = path.join(
26
+ CACHE_DIR_RELATIVE_PATH,
27
+ '.install.lock',
28
+ );
29
+
30
+ /**
31
+ * Relative path to lockfile used when linking an extension via `appium`
32
+ */
33
+ export const LINK_LOCKFILE_RELATIVE_PATH = path.join(
34
+ CACHE_DIR_RELATIVE_PATH,
35
+ '.link.lock',
36
+ );
37
+
38
+ /**
39
+ * XXX: This should probably be a singleton, but it isn't. Maybe this module should just export functions?
40
+ */
41
+ export class NPM {
42
+ /**
43
+ * Returns path to "install" lockfile
44
+ * @private
45
+ * @param {string} cwd
46
+ */
47
+ _getInstallLockfilePath (cwd) {
48
+ return path.join(cwd, INSTALL_LOCKFILE_RELATIVE_PATH);
49
+ }
50
+
51
+ /**
52
+ * Returns path to "link" lockfile
53
+ * @private
54
+ * @param {string} cwd
55
+ */
56
+ _getLinkLockfilePath (cwd) {
57
+ return path.join(cwd, LINK_LOCKFILE_RELATIVE_PATH);
58
+ }
59
+
60
+ /**
61
+ * Execute `npm` with given args.
62
+ *
63
+ * If the process exits with a nonzero code, the contents of `STDOUT` and `STDERR` will be in the
64
+ * `message` of the {@link TeenProcessExecError} rejected.
65
+ * @param {string} cmd
66
+ * @param {string[]} args
67
+ * @param {ExecOpts} opts
68
+ * @param {TeenProcessExecOpts} [execOpts]
69
+ */
70
+ async exec (cmd, args, opts, execOpts = {}) {
71
+ let { cwd, json, lockFile } = opts;
72
+
73
+ // make sure we perform the current operation in cwd
74
+ execOpts = {...execOpts, cwd};
75
+
76
+ args.unshift(cmd);
77
+ if (json) {
78
+ args.push('--json');
79
+ }
80
+ const npmCmd = system.isWindows() ? 'npm.cmd' : 'npm';
81
+ let runner = async () => await exec(npmCmd, args, execOpts);
82
+ if (lockFile) {
83
+ const acquireLock = util.getLockFileGuard(lockFile);
84
+ const _runner = runner;
85
+ runner = async () => await acquireLock(_runner);
86
+ }
87
+
88
+ let ret;
89
+ try {
90
+ const {stdout, stderr, code} = await runner();
91
+ ret = /** @type {TeenProcessExecResult} */({stdout, stderr, code});
92
+ // if possible, parse NPM's json output. During NPM install 3rd-party
93
+ // packages can write to stdout, so sometimes the json output can't be
94
+ // guaranteed to be parseable
95
+ try {
96
+ ret.json = JSON.parse(stdout);
97
+ } catch (ign) {}
98
+ } catch (e) {
99
+ const {stdout = '', stderr = '', code = null} = /** @type {TeenProcessExecError} */(e);
100
+ const err = new Error(`npm command '${args.join(' ')}' failed with code ${code}.\n\nSTDOUT:\n${stdout.trim()}\n\nSTDERR:\n${stderr.trim()}`);
101
+ throw err;
102
+ }
103
+ return ret;
104
+ }
105
+
106
+ /**
107
+ * @param {string} cwd
108
+ * @param {string} pkg
109
+ */
110
+ async getLatestVersion (cwd, pkg) {
111
+ return (await this.exec('view', [pkg, 'dist-tags'], {
112
+ json: true,
113
+ cwd
114
+ })).json?.latest;
115
+ }
116
+
117
+ /**
118
+ * @param {string} cwd
119
+ * @param {string} pkg
120
+ * @param {string} curVersion
121
+ */
122
+ async getLatestSafeUpgradeVersion (cwd, pkg, curVersion) {
123
+ const allVersions = (await this.exec('view', [pkg, 'versions'], {
124
+ json: true,
125
+ cwd
126
+ })).json;
127
+ return this.getLatestSafeUpgradeFromVersions(curVersion, allVersions);
128
+ }
129
+
130
+ /**
131
+ * Runs `npm ls`, optionally for a particular package.
132
+ * @param {string} cwd
133
+ * @param {string} [pkg]
134
+ */
135
+ async list (cwd, pkg) {
136
+ return (await this.exec('list', pkg ? [pkg] : [], {cwd, json: true})).json;
137
+ }
138
+
139
+ /**
140
+ * Given a current version and a list of all versions for a package, return the version which is
141
+ * the highest safely-upgradable version (meaning not crossing any major revision boundaries, and
142
+ * not including any alpha/beta/rc versions)
143
+ *
144
+ * @param {string} curVersion - the current version of a package
145
+ * @param {Array<string>} allVersions - a list of version strings
146
+ *
147
+ * @return {string|null} - the highest safely-upgradable version, or null if there isn't one
148
+ */
149
+ getLatestSafeUpgradeFromVersions (curVersion, allVersions) {
150
+ let safeUpgradeVer = null;
151
+ const curSemver = semver.parse(curVersion);
152
+ if (curSemver === null) {
153
+ throw new Error(`Could not parse current version '${curVersion}'`);
154
+ }
155
+ for (const testVer of allVersions) {
156
+ const testSemver = semver.parse(testVer);
157
+ if (testSemver === null) {
158
+ throw new Error(`Could not parse version to test against: '${testVer}'`);
159
+ }
160
+ // if the test version is a prerelease, ignore it
161
+ if (testSemver.prerelease.length > 0) {
162
+ continue;
163
+ }
164
+ // if the current version is later than the test version, skip this test version
165
+ if (curSemver.compare(testSemver) === 1) {
166
+ continue;
167
+ }
168
+ // if the test version is newer, but crosses a major revision boundary, also skip it
169
+ if (testSemver.major > curSemver.major) {
170
+ continue;
171
+ }
172
+ // otherwise this version is safe to upgrade to. But there might be multiple ones of this
173
+ // kind, so keep iterating and keeping the highest
174
+ if (safeUpgradeVer === null || testSemver.compare(safeUpgradeVer) === 1) {
175
+ safeUpgradeVer = testSemver;
176
+ }
177
+ }
178
+ if (safeUpgradeVer) {
179
+ safeUpgradeVer = safeUpgradeVer.format();
180
+ }
181
+ return safeUpgradeVer;
182
+ }
183
+
184
+ /**
185
+ * Installs a package w/ `npm`
186
+ * @param {string} cwd
187
+ * @param {string} pkgName
188
+ * @param {InstallPackageOpts} [opts]
189
+ * @returns {Promise<import('type-fest').PackageJson>}
190
+ */
191
+ async installPackage (cwd, pkgName, {pkgVer} = {}) {
192
+ // not only this, this directory needs a 'package.json' inside of it, otherwise, if any
193
+ // directory in the filesystem tree ABOVE cwd happens to have a package.json or a node_modules
194
+ // dir in it, NPM will install the module up there instead (silly NPM)
195
+ const dummyPkgJson = path.resolve(cwd, 'package.json');
196
+ if (!await fs.exists(dummyPkgJson)) {
197
+ await fs.writeFile(dummyPkgJson, '{}');
198
+ }
199
+
200
+ const res = await this.exec('install', [
201
+ '--no-save',
202
+ '--global-style',
203
+ '--no-package-lock',
204
+ pkgVer ? `${pkgName}@${pkgVer}` : pkgName
205
+ ], {
206
+ cwd,
207
+ json: true,
208
+ lockFile: this._getInstallLockfilePath(cwd)
209
+ });
210
+
211
+ if (res.json) {
212
+ // we parsed a valid json response, so if we got an error here, return that
213
+ // message straightaway
214
+ if (res.json.error) {
215
+ throw new Error(res.json.error);
216
+ }
217
+ }
218
+
219
+ // Now read package data from the installed package to return, and make sure
220
+ // everything got installed ok. Remember, pkgName might end up with a / in it due to an npm
221
+ // org, so if so, that will get correctly exploded into multiple directories, by path.resolve here
222
+ // (even on Windows!)
223
+ const pkgJsonPath = resolveFrom(cwd, `${pkgName}/package.json`);
224
+ try {
225
+ return require(pkgJsonPath);
226
+ } catch {
227
+ throw new Error('The package was not downloaded correctly; its package.json ' +
228
+ 'did not exist or was unreadable. We looked for it at ' +
229
+ pkgJsonPath);
230
+ }
231
+ }
232
+
233
+ /**
234
+ * @todo: I think this can be an `install` instead of a `link`.
235
+ * @param {string} cwd
236
+ * @param {string} pkgPath
237
+ */
238
+ async linkPackage (cwd, pkgPath) {
239
+ // from the path alone we don't know the npm package name, so we need to
240
+ // look in package.json
241
+ let pkgName;
242
+ try {
243
+ pkgName = require(path.resolve(pkgPath, 'package.json')).name;
244
+ } catch {
245
+ throw new Error('Could not find package.json inside the package path ' +
246
+ `provided: ${pkgPath}`);
247
+ }
248
+
249
+ // this is added to handle commands with relative paths
250
+ // ie: "node . driver install --source=local ../fake-driver"
251
+ pkgPath = path.resolve(process.cwd(), pkgPath);
252
+
253
+ // call link with --no-package-lock to ensure no corruption while installing local packages
254
+ const args = [
255
+ '--global-style',
256
+ '--no-package-lock',
257
+ pkgPath
258
+ ];
259
+ const res = await this.exec('link', args, {cwd, lockFile: this._getLinkLockfilePath(cwd)});
260
+ if (res.json && res.json.error) {
261
+ throw new Error(res.json.error);
262
+ }
263
+
264
+ // now ensure it was linked to the correct place
265
+ try {
266
+ return require(resolveFrom(cwd, `${pkgName}/package.json`));
267
+ } catch {
268
+ throw new Error('The package was not linked correctly; its package.json ' +
269
+ 'did not exist or was unreadable');
270
+ }
271
+ }
272
+
273
+ /**
274
+ * @param {string} cwd
275
+ * @param {string} pkg
276
+ */
277
+ async uninstallPackage (cwd, pkg) {
278
+ await this.exec('uninstall', [pkg], {
279
+ cwd,
280
+ lockFile: this._getInstallLockfilePath(cwd)
281
+ });
282
+ }
283
+ }
284
+
285
+ export const npm = new NPM();
286
+
287
+ /**
288
+ * Options for {@link NPM.installPackage}
289
+ * @typedef InstallPackageOpts
290
+ * @property {string} [pkgVer] - the version of the package to install
291
+ */
292
+
293
+ /**
294
+ * Options for {@link NPM.exec}
295
+ * @typedef ExecOpts
296
+ * @property {string} cwd - Current working directory
297
+ * @property {boolean} [json] - If `true`, supply `--json` flag to npm and resolve w/ parsed JSON
298
+ * @property {string} [lockFile] - Path to lockfile to use
299
+ */
300
+
301
+ // THESE TYPES SHOULD BE IN TEEN PROCESS, NOT HERE
302
+
303
+ /**
304
+ * Result from a non-zero-exit execution of `appium`
305
+ * @typedef TeenProcessExecResult
306
+ * @property {string} stdout - Stdout
307
+ * @property {string} stderr - Stderr
308
+ * @property {number?} code - Exit code
309
+ * @property {any} json - JSON parsed from stdout
310
+ */
311
+
312
+ /**
313
+ * Extra props `teen_process.exec` adds to its error objects
314
+ * @typedef TeenProcessExecErrorProps
315
+ * @property {string} stdout - STDOUT
316
+ * @property {string} stderr - STDERR
317
+ * @property {number?} code - Exit code
318
+ */
319
+
320
+ /**
321
+ * Options unique to `teen_process.exec`. I probably missed some
322
+ * @typedef TeenProcessExecExtraOpts
323
+ * @property {number} [maxStdoutBufferSize]
324
+ * @property {number} [maxStderrBufferSize]
325
+ */
326
+
327
+ /**
328
+ * All options for `teen_process.exec`
329
+ * @typedef {import('child_process').SpawnOptions & TeenProcessExecExtraOpts} TeenProcessExecOpts
330
+ */
331
+
332
+ /**
333
+ * Error thrown by `teen_process.exec`
334
+ * @typedef {Error & TeenProcessExecErrorProps} TeenProcessExecError
335
+ */
package/lib/tempdir.js CHANGED
@@ -13,7 +13,7 @@ const RDWR_EXCL = cnst.O_CREAT | cnst.O_TRUNC | cnst.O_RDWR | cnst.O_EXCL;
13
13
  * - No `process.env.APPIUM_TMP_DIR`: `/var/folders/34/2222sh8n27d6rcp7jqlkw8km0000gn/T/xxxxxxxx.yyyy`
14
14
  * - With `process.env.APPIUM_TMP_DIR = '/path/to/root'`: `/path/to/root/xxxxxxxx.yyyy`
15
15
  *
16
- * @returns {string} A path to the temporary directory
16
+ * @returns {Promise<string>} A path to the temporary directory
17
17
  */
18
18
  async function tempDir () {
19
19
  const now = new Date();
@@ -33,7 +33,7 @@ async function tempDir () {
33
33
  }
34
34
 
35
35
  /**
36
- * @typedef {Object} Affixes
36
+ * @typedef Affixes
37
37
  * @property {string} prefix - prefix of the temp directory name
38
38
  * @property {string} suffix - suffix of the temp directory name
39
39
  */
@@ -44,7 +44,7 @@ async function tempDir () {
44
44
  *
45
45
  * @param {string|Affixes} rawAffixes
46
46
  * @param {?string} defaultPrefix
47
- * @returns {string} A path to the temporary directory with rawAffixes and defaultPrefix
47
+ * @returns {Promise<string>} A path to the temporary directory with rawAffixes and defaultPrefix
48
48
  */
49
49
  async function path (rawAffixes, defaultPrefix) {
50
50
  const affixes = parseAffixes(rawAffixes, defaultPrefix);
@@ -54,7 +54,7 @@ async function path (rawAffixes, defaultPrefix) {
54
54
  }
55
55
 
56
56
  /**
57
- * @typedef {Object} OpenedAffixes
57
+ * @typedef OpenedAffixes
58
58
  * @property {string} path - The path to file
59
59
  * @property {integer} fd - The file descriptor opened
60
60
  */
@@ -64,7 +64,7 @@ async function path (rawAffixes, defaultPrefix) {
64
64
  * with arbitrary prefix/suffix for the directory name and return it as open.
65
65
  *
66
66
  * @param {Affixes} affixes
67
- * @returns {OpenedAffixes}
67
+ * @returns {Promise<OpenedAffixes>}
68
68
  */
69
69
  async function open (affixes) {
70
70
  const filePath = await path(affixes, 'f-');
@@ -116,7 +116,7 @@ const openDir = tempDir;
116
116
  /**
117
117
  * Returns a path to a temporary directory whcih is defined as static in the same process
118
118
  *
119
- * @returns {string} A temp directory path whcih is defined as static in the same process
119
+ * @returns {Promise<string>} A temp directory path whcih is defined as static in the same process
120
120
  */
121
121
  async function staticDir () { // eslint-disable-line require-await
122
122
  return _static;
package/lib/util.js CHANGED
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+
1
3
  import B from 'bluebird';
2
4
  import _ from 'lodash';
3
5
  import os from 'os';
@@ -75,6 +77,7 @@ function localIp () {
75
77
  let ip = _.chain(os.networkInterfaces())
76
78
  .values()
77
79
  .flatten()
80
+ // @ts-ignore
78
81
  .filter(function (val) {
79
82
  return (val.family === 'IPv4' && val.internal === false);
80
83
  })
@@ -217,16 +220,16 @@ function filterObject (obj, predicate) {
217
220
  * if it is less than zero.
218
221
  */
219
222
  function toReadableSizeString (bytes) {
220
- const intBytes = parseInt(bytes, 10);
223
+ const intBytes = parseInt(String(bytes), 10);
221
224
  if (isNaN(intBytes) || intBytes < 0) {
222
225
  throw new Error(`Cannot convert '${bytes}' to a readable size format`);
223
226
  }
224
227
  if (intBytes >= GiB) {
225
- return `${parseFloat(intBytes / (GiB * 1.0)).toFixed(2)} GB`;
228
+ return `${(intBytes / (GiB * 1.0)).toFixed(2)} GB`;
226
229
  } else if (intBytes >= MiB) {
227
- return `${parseFloat(intBytes / (MiB * 1.0)).toFixed(2)} MB`;
230
+ return `${(intBytes / (MiB * 1.0)).toFixed(2)} MB`;
228
231
  } else if (intBytes >= KiB) {
229
- return `${parseFloat(intBytes / (KiB * 1.0)).toFixed(2)} KB`;
232
+ return `${(intBytes / (KiB * 1.0)).toFixed(2)} KB`;
230
233
  }
231
234
  return `${intBytes} B`;
232
235
  }
@@ -260,7 +263,7 @@ function isSubPath (originalPath, root, forcePosix = null) {
260
263
  * @param {string} path1 - Absolute or relative path to a file/folder
261
264
  * @param {string} path2 - Absolute or relative path to a file/folder
262
265
  * @param {...string} pathN - Zero or more absolute or relative paths to files/folders
263
- * @returns {boolean} true if all paths are pointing to the same file system item
266
+ * @returns {Promise<boolean>} true if all paths are pointing to the same file system item
264
267
  */
265
268
  async function isSameDestination (path1, path2, ...pathN) {
266
269
  const allPaths = [path1, path2, ...pathN];
@@ -288,19 +291,20 @@ async function isSameDestination (path1, path2, ...pathN) {
288
291
  /**
289
292
  * Coerces the given number/string to a valid version string
290
293
  *
291
- * @param {string|number} ver - Version string to coerce
292
- * @param {boolean} strict [true] - If true then an exception will be thrown
294
+ * @template {boolean} [Strict=true]
295
+ * @param {string} ver - Version string to coerce
296
+ * @param {Strict} [strict] - If `true` then an exception will be thrown
293
297
  * if `ver` cannot be coerced
294
- * @returns {string} Coerced version number or null if the string cannot be
298
+ * @returns {Strict extends true ? string : string|null} Coerced version number or null if the string cannot be
295
299
  * coerced and strict mode is disabled
296
300
  * @throws {Error} if strict mode is enabled and `ver` cannot be coerced
297
301
  */
298
- function coerceVersion (ver, strict = true) {
302
+ function coerceVersion (ver, strict = /** @type {Strict} */(true)) {
299
303
  const result = semver.valid(semver.coerce(`${ver}`));
300
304
  if (strict && !result) {
301
305
  throw new Error(`'${ver}' cannot be coerced to a valid version number`);
302
306
  }
303
- return result;
307
+ return /** @type {Strict extends true ? string : string|null} */(result);
304
308
  }
305
309
 
306
310
  const SUPPORTED_OPERATORS = ['==', '!=', '>', '<', '>=', '<=', '='];
@@ -308,9 +312,9 @@ const SUPPORTED_OPERATORS = ['==', '!=', '>', '<', '>=', '<=', '='];
308
312
  /**
309
313
  * Compares two version strings
310
314
  *
311
- * @param {string|number} ver1 - The first version number to compare. Should be a valid
315
+ * @param {string} ver1 - The first version number to compare. Should be a valid
312
316
  * version number supported by semver parser.
313
- * @param {string|number} ver2 - The second version number to compare. Should be a valid
317
+ * @param {string} ver2 - The second version number to compare. Should be a valid
314
318
  * version number supported by semver parser.
315
319
  * @param {string} operator - One of supported version number operators:
316
320
  * ==, !=, >, <, <=, >=, =
@@ -333,7 +337,7 @@ function compareVersions (ver1, operator, ver2) {
333
337
  * Add appropriate quotes to command arguments. See https://github.com/substack/node-shell-quote
334
338
  * for more details
335
339
  *
336
- * @param {string|Array<string>} - The arguments that will be parsed
340
+ * @param {string|string[]} args - The arguments that will be parsed
337
341
  * @returns {string} - The arguments, quoted
338
342
  */
339
343
  function quote (args) {
@@ -354,8 +358,8 @@ function unleakString (s) {
354
358
 
355
359
 
356
360
  /**
357
- * @typedef {Object} PluralizeOptions
358
- * @property {?boolean} inclusive [false] - Whether to prefix with the number (e.g., 3 ducks)
361
+ * @typedef PluralizeOptions
362
+ * @property {boolean} [inclusive=false] - Whether to prefix with the number (e.g., 3 ducks)
359
363
  */
360
364
 
361
365
  /**
@@ -363,7 +367,7 @@ function unleakString (s) {
363
367
  *
364
368
  * @param {string} word - The word to pluralize
365
369
  * @param {number} count - How many of the word exist
366
- * @param {?PluralizeOptions|boolean} options|inclusive - options for word pluralization,
370
+ * @param {PluralizeOptions|boolean} options - options for word pluralization,
367
371
  * or a boolean indicating the options.inclusive property
368
372
  * @returns {string} The word pluralized according to the number
369
373
  */
@@ -380,8 +384,8 @@ function pluralize (word, count, options = {}) {
380
384
  }
381
385
 
382
386
  /**
383
- * @typedef {Object} EncodingOptions
384
- * @property {number} maxSize [1073741824] The maximum size of
387
+ * @typedef EncodingOptions
388
+ * @property {number} [maxSize=1073741824] The maximum size of
385
389
  * the resulting buffer in bytes. This is set to 1GB by default, because
386
390
  * Appium limits the maximum HTTP body size to 1GB. Also, the NodeJS heap
387
391
  * size must be enough to keep the resulting object (usually this size is
@@ -395,7 +399,7 @@ function pluralize (word, count, options = {}) {
395
399
  *
396
400
  * @param {string} srcPath The full path to the file being encoded
397
401
  * @param {EncodingOptions} opts
398
- * @returns {Buffer} base64-encoded content of the source file as memory buffer
402
+ * @returns {Promise<Buffer>} base64-encoded content of the source file as memory buffer
399
403
  * @throws {Error} if there was an error while reading the source file
400
404
  * or the source file is too
401
405
  */
@@ -445,9 +449,9 @@ async function toInMemoryBase64 (srcPath, opts = {}) {
445
449
  }
446
450
 
447
451
  /**
448
- * @typedef {Object} LockFileOptions
449
- * @property {number} timeout [120] The max time in seconds to wait for the lock
450
- * @property {boolean} tryRecovery [false] Whether to try lock recovery if
452
+ * @typedef LockFileOptions
453
+ * @property {number} [timeout=120] The max time in seconds to wait for the lock
454
+ * @property {boolean} [tryRecovery=false] Whether to try lock recovery if
451
455
  * the first attempt to acquire it timed out.
452
456
  */
453
457
 
@@ -458,7 +462,7 @@ async function toInMemoryBase64 (srcPath, opts = {}) {
458
462
  *
459
463
  * @param {string} lockFile The full path to the file used for the lock
460
464
  * @param {LockFileOptions} opts
461
- * @returns {AsyncFunction} async function that takes another async function defining the locked
465
+ * @returns {(behavior: () => Promise<void>) => Promise<void>} async function that takes another async function defining the locked
462
466
  * behavior
463
467
  */
464
468
  function getLockFileGuard (lockFile, opts = {}) {
@@ -467,7 +471,7 @@ function getLockFileGuard (lockFile, opts = {}) {
467
471
  tryRecovery = false,
468
472
  } = opts;
469
473
 
470
- const lock = B.promisify(_lockfile.lock);
474
+ const lock = /** @type {(lockfile: string, opts: import('lockfile').Options)=>B<void>} */(B.promisify(_lockfile.lock));
471
475
  const check = B.promisify(_lockfile.check);
472
476
  const unlock = B.promisify(_lockfile.unlock);
473
477
 
package/lib/zip.js CHANGED
@@ -4,7 +4,6 @@ import yauzl from 'yauzl';
4
4
  import archiver from 'archiver';
5
5
  import { createWriteStream } from 'fs';
6
6
  import path from 'path';
7
- import { mkdirp } from '../lib/mkdirp';
8
7
  import stream from 'stream';
9
8
  import fs from './fs';
10
9
  import { isWindows } from './system';
@@ -169,7 +168,7 @@ class ZipExtractor {
169
168
 
170
169
 
171
170
  /**
172
- * @typedef {Object} ExtractAllOptions
171
+ * @typedef ExtractAllOptions
173
172
  * @property {?string} fileNamesEncoding The encoding to use for extracted file names.
174
173
  * For ZIP archives created on MacOS it is usually expected to be `utf8`.
175
174
  * By default it is autodetected based on the entry metadata and is only needed to be set explicitly
@@ -261,11 +260,11 @@ async function _extractEntryTo (zipFile, entry, destDir) {
261
260
  // Create dest directory if doesn't exist already
262
261
  if (/\/$/.test(entry.fileName)) {
263
262
  if (!await fs.exists(dstPath)) {
264
- await mkdirp(dstPath);
263
+ await fs.mkdirp(dstPath);
265
264
  }
266
265
  return;
267
266
  } else if (!await fs.exists(path.dirname(dstPath))) {
268
- await mkdirp(path.dirname(dstPath));
267
+ await fs.mkdirp(path.dirname(dstPath));
269
268
  }
270
269
 
271
270
  // Create a write stream
@@ -294,7 +293,7 @@ async function _extractEntryTo (zipFile, entry, destDir) {
294
293
  }
295
294
 
296
295
  /**
297
- * @typedef {Object} ZipEntry
296
+ * @typedef ZipEntry
298
297
  * @property {yauzl.ZipEntry} entry The actual entry instance
299
298
  * @property {function} extractEntryTo An async function, which accepts one parameter.
300
299
  * This parameter contains the destination folder path to which this function is going to extract the entry.
@@ -335,7 +334,7 @@ async function readEntries (zipFilePath, onEntry) {
335
334
  }
336
335
 
337
336
  /**
338
- * @typedef {Object} ZipOptions
337
+ * @typedef ZipOptions
339
338
  * @property {boolean} encodeToBase64 [false] Whether to encode
340
339
  * the resulting archive to a base64-encoded string
341
340
  * @property {boolean} isMetered [true] Whether to log the actual
@@ -475,13 +474,13 @@ async function assertValidZip (filePath) {
475
474
  }
476
475
 
477
476
  /**
478
- * @typedef {Object} ZipCompressionOptions
477
+ * @typedef ZipCompressionOptions
479
478
  * @property {number} level [9] - Compression level in range 0..9
480
479
  * (greater numbers mean better compression, but longer processing time)
481
480
  */
482
481
 
483
482
  /**
484
- * @typedef {Object} ZipSourceOptions
483
+ * @typedef ZipSourceOptions
485
484
  * @property {!string} pattern ['**\/*'] - GLOB pattern for compression
486
485
  * @property {!string} cwd - The source root folder (the parent folder of
487
486
  * the destination file by default)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appium/support",
3
- "version": "2.55.4",
3
+ "version": "2.56.0",
4
4
  "description": "Support libs used across appium packages",
5
5
  "keywords": [
6
6
  "automation",
@@ -12,12 +12,14 @@
12
12
  "firefoxos",
13
13
  "testing"
14
14
  ],
15
+ "homepage": "https://appium.io",
15
16
  "bugs": {
16
17
  "url": "https://github.com/appium/appium/issues"
17
18
  },
18
19
  "repository": {
19
20
  "type": "git",
20
- "url": "https://github.com/appium/appium.git"
21
+ "url": "https://github.com/appium/appium.git",
22
+ "directory": "packages/support"
21
23
  },
22
24
  "license": "Apache-2.0",
23
25
  "author": "https://github.com/appium",
@@ -29,15 +31,23 @@
29
31
  "lib",
30
32
  "build"
31
33
  ],
34
+ "scripts": {
35
+ "build": "babel lib --root-mode=upward --delete-dir-on-start --out-dir=build/lib",
36
+ "dev": "npm run build -- --watch",
37
+ "fix": "npm run lint -- --fix",
38
+ "lint": "eslint -c ../../.eslintrc --ignore-path ../../.eslintignore .",
39
+ "test": "npm run test:unit",
40
+ "test:e2e": "mocha --require ../../test/setup-babel.js --timeout 20s --slow 10s \"./test/e2e/**/*.spec.js\"",
41
+ "test:unit": "mocha --require ../../test/setup-babel.js \"./test/unit/**/*.spec.js\""
42
+ },
32
43
  "dependencies": {
33
- "@babel/runtime": "7.16.3",
44
+ "@babel/runtime": "7.17.8",
34
45
  "archiver": "5.3.0",
35
- "axios": "0.24.0",
46
+ "axios": "0.26.1",
36
47
  "base64-stream": "1.0.0",
37
48
  "bluebird": "3.7.2",
38
49
  "bplist-creator": "0.1.0",
39
50
  "bplist-parser": "0.3.1",
40
- "find-root": "1.1.0",
41
51
  "form-data": "4.0.0",
42
52
  "get-stream": "6.0.1",
43
53
  "glob": "7.2.0",
@@ -46,15 +56,16 @@
46
56
  "klaw": "3.0.0",
47
57
  "lockfile": "1.0.4",
48
58
  "lodash": "4.17.21",
49
- "mkdirp": "1.0.4",
50
59
  "moment": "2.29.1",
51
60
  "mv": "2.1.1",
52
61
  "ncp": "2.0.0",
53
- "npmlog": "5.0.1",
54
- "opencv-bindings": "^4.5.5",
62
+ "npmlog": "6.0.1",
63
+ "opencv-bindings": "4.5.5",
64
+ "pkg-dir": "5.0.0",
55
65
  "plist": "3.0.4",
56
66
  "pluralize": "8.0.0",
57
67
  "pngjs": "6.0.0",
68
+ "read-pkg": "5.2.0",
58
69
  "rimraf": "3.0.2",
59
70
  "sanitize-filename": "1.6.3",
60
71
  "semver": "7.3.5",
@@ -72,6 +83,5 @@
72
83
  "publishConfig": {
73
84
  "access": "public"
74
85
  },
75
- "homepage": "https://appium.io",
76
- "gitHead": "42f4a2de2d763d57cf0bdb6fb6c9a3bc9c3d232f"
86
+ "gitHead": "f5cce0f29d31699decea63ed94c4506f7af469df"
77
87
  }