appium-adb 14.3.5 → 14.4.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 (134) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/lib/adb.d.ts +9 -4
  3. package/build/lib/adb.d.ts.map +1 -1
  4. package/build/lib/adb.js +8 -9
  5. package/build/lib/adb.js.map +1 -1
  6. package/build/lib/index.d.ts +1 -1
  7. package/build/lib/index.d.ts.map +1 -1
  8. package/build/lib/index.js +2 -2
  9. package/build/lib/index.js.map +1 -1
  10. package/build/lib/logcat.d.ts.map +1 -1
  11. package/build/lib/logcat.js +6 -14
  12. package/build/lib/logcat.js.map +1 -1
  13. package/build/lib/tools/aab-utils.d.ts.map +1 -1
  14. package/build/lib/tools/aab-utils.js +2 -2
  15. package/build/lib/tools/aab-utils.js.map +1 -1
  16. package/build/lib/tools/android-manifest.d.ts.map +1 -1
  17. package/build/lib/tools/android-manifest.js +11 -12
  18. package/build/lib/tools/android-manifest.js.map +1 -1
  19. package/build/lib/tools/apk-signing.d.ts.map +1 -1
  20. package/build/lib/tools/apk-signing.js +18 -19
  21. package/build/lib/tools/apk-signing.js.map +1 -1
  22. package/build/lib/tools/apk-utils.d.ts.map +1 -1
  23. package/build/lib/tools/apk-utils.js +39 -40
  24. package/build/lib/tools/apk-utils.js.map +1 -1
  25. package/build/lib/tools/apks-utils.d.ts.map +1 -1
  26. package/build/lib/tools/apks-utils.js +8 -9
  27. package/build/lib/tools/apks-utils.js.map +1 -1
  28. package/build/lib/tools/app-commands.d.ts.map +1 -1
  29. package/build/lib/tools/app-commands.js +37 -36
  30. package/build/lib/tools/app-commands.js.map +1 -1
  31. package/build/lib/tools/device-settings.d.ts.map +1 -1
  32. package/build/lib/tools/device-settings.js +17 -18
  33. package/build/lib/tools/device-settings.js.map +1 -1
  34. package/build/lib/tools/emulator-commands.d.ts.map +1 -1
  35. package/build/lib/tools/emulator-commands.js +22 -23
  36. package/build/lib/tools/emulator-commands.js.map +1 -1
  37. package/build/lib/tools/fs-commands.d.ts.map +1 -1
  38. package/build/lib/tools/fs-commands.js +5 -4
  39. package/build/lib/tools/fs-commands.js.map +1 -1
  40. package/build/lib/tools/general-commands.d.ts.map +1 -1
  41. package/build/lib/tools/general-commands.js +29 -29
  42. package/build/lib/tools/general-commands.js.map +1 -1
  43. package/build/lib/tools/keyboard-commands.d.ts.map +1 -1
  44. package/build/lib/tools/keyboard-commands.js +6 -4
  45. package/build/lib/tools/keyboard-commands.js.map +1 -1
  46. package/build/lib/tools/lockmgmt.d.ts.map +1 -1
  47. package/build/lib/tools/lockmgmt.js +17 -20
  48. package/build/lib/tools/lockmgmt.js.map +1 -1
  49. package/build/lib/tools/logcat-commands.d.ts.map +1 -1
  50. package/build/lib/tools/logcat-commands.js +5 -9
  51. package/build/lib/tools/logcat-commands.js.map +1 -1
  52. package/build/lib/tools/network-commands.d.ts.map +1 -1
  53. package/build/lib/tools/network-commands.js +1 -5
  54. package/build/lib/tools/network-commands.js.map +1 -1
  55. package/build/lib/tools/process-commands.d.ts.map +1 -1
  56. package/build/lib/tools/process-commands.js +11 -12
  57. package/build/lib/tools/process-commands.js.map +1 -1
  58. package/build/lib/tools/system-calls.d.ts +12 -5
  59. package/build/lib/tools/system-calls.d.ts.map +1 -1
  60. package/build/lib/tools/system-calls.js +56 -50
  61. package/build/lib/tools/system-calls.js.map +1 -1
  62. package/build/lib/tools/types.d.ts +1 -1
  63. package/build/lib/tools/types.d.ts.map +1 -1
  64. package/build/lib/utils/helpers/constants.d.ts +6 -0
  65. package/build/lib/utils/helpers/constants.d.ts.map +1 -0
  66. package/build/lib/utils/helpers/constants.js +9 -0
  67. package/build/lib/utils/helpers/constants.js.map +1 -0
  68. package/build/lib/utils/helpers/index.d.ts +6 -0
  69. package/build/lib/utils/helpers/index.d.ts.map +1 -0
  70. package/build/lib/utils/helpers/index.js +21 -0
  71. package/build/lib/utils/helpers/index.js.map +1 -0
  72. package/build/lib/utils/helpers/install.d.ts +16 -0
  73. package/build/lib/utils/helpers/install.d.ts.map +1 -0
  74. package/build/lib/utils/helpers/install.js +39 -0
  75. package/build/lib/utils/helpers/install.js.map +1 -0
  76. package/build/lib/utils/helpers/manifest.d.ts +10 -0
  77. package/build/lib/utils/helpers/manifest.d.ts.map +1 -0
  78. package/build/lib/utils/helpers/manifest.js +124 -0
  79. package/build/lib/utils/helpers/manifest.js.map +1 -0
  80. package/build/lib/utils/helpers/resource.d.ts +11 -0
  81. package/build/lib/utils/helpers/resource.d.ts.map +1 -0
  82. package/build/lib/utils/helpers/resource.js +59 -0
  83. package/build/lib/utils/helpers/resource.js.map +1 -0
  84. package/build/lib/utils/helpers/sdk.d.ts +20 -0
  85. package/build/lib/utils/helpers/sdk.d.ts.map +1 -0
  86. package/build/lib/utils/helpers/sdk.js +80 -0
  87. package/build/lib/utils/helpers/sdk.js.map +1 -0
  88. package/build/lib/utils/index.d.ts +40 -0
  89. package/build/lib/utils/index.d.ts.map +1 -0
  90. package/build/lib/utils/index.js +58 -0
  91. package/build/lib/utils/index.js.map +1 -0
  92. package/build/lib/utils/lodash/core.d.ts +9 -0
  93. package/build/lib/utils/lodash/core.d.ts.map +1 -0
  94. package/build/lib/utils/lodash/core.js +60 -0
  95. package/build/lib/utils/lodash/core.js.map +1 -0
  96. package/build/lib/utils/lodash/index.d.ts +2 -0
  97. package/build/lib/utils/lodash/index.d.ts.map +1 -0
  98. package/build/lib/utils/lodash/index.js +18 -0
  99. package/build/lib/utils/lodash/index.js.map +1 -0
  100. package/lib/adb.ts +14 -6
  101. package/lib/index.ts +1 -1
  102. package/lib/logcat.ts +6 -11
  103. package/lib/tools/aab-utils.ts +1 -1
  104. package/lib/tools/android-manifest.ts +4 -4
  105. package/lib/tools/apk-signing.ts +11 -7
  106. package/lib/tools/apk-utils.ts +41 -42
  107. package/lib/tools/apks-utils.ts +4 -5
  108. package/lib/tools/app-commands.ts +40 -34
  109. package/lib/tools/device-settings.ts +17 -15
  110. package/lib/tools/emulator-commands.ts +22 -23
  111. package/lib/tools/fs-commands.ts +5 -4
  112. package/lib/tools/general-commands.ts +32 -27
  113. package/lib/tools/keyboard-commands.ts +6 -4
  114. package/lib/tools/lockmgmt.ts +17 -13
  115. package/lib/tools/logcat-commands.ts +5 -6
  116. package/lib/tools/network-commands.ts +1 -2
  117. package/lib/tools/process-commands.ts +11 -9
  118. package/lib/tools/system-calls.ts +54 -46
  119. package/lib/tools/types.ts +1 -1
  120. package/lib/utils/helpers/constants.ts +6 -0
  121. package/lib/utils/helpers/index.ts +10 -0
  122. package/lib/utils/helpers/install.ts +50 -0
  123. package/lib/utils/helpers/manifest.ts +127 -0
  124. package/lib/utils/helpers/resource.ts +63 -0
  125. package/lib/utils/helpers/sdk.ts +81 -0
  126. package/lib/utils/index.ts +25 -0
  127. package/lib/utils/lodash/core.ts +65 -0
  128. package/lib/utils/lodash/index.ts +1 -0
  129. package/package.json +2 -4
  130. package/build/lib/helpers.d.ts +0 -47
  131. package/build/lib/helpers.d.ts.map +0 -1
  132. package/build/lib/helpers.js +0 -283
  133. package/build/lib/helpers.js.map +0 -1
  134. package/lib/helpers.ts +0 -323
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultsDeep = exports.pick = exports.zip = exports.intersectionWith = exports.defaults = exports.cloneDeep = void 0;
4
+ const support_1 = require("@appium/support");
5
+ const cloneDeep = (value) => {
6
+ if (typeof globalThis.structuredClone === 'function') {
7
+ return globalThis.structuredClone(value);
8
+ }
9
+ return JSON.parse(JSON.stringify(value));
10
+ };
11
+ exports.cloneDeep = cloneDeep;
12
+ const defaults = (target, ...sources) => {
13
+ for (const source of sources) {
14
+ if (!source) {
15
+ continue;
16
+ }
17
+ for (const [key, value] of Object.entries(source)) {
18
+ if (target[key] === undefined) {
19
+ target[key] = value;
20
+ }
21
+ }
22
+ }
23
+ return target;
24
+ };
25
+ exports.defaults = defaults;
26
+ const _defaultsDeep = (target, ...sources) => {
27
+ for (const source of sources) {
28
+ if (!source) {
29
+ continue;
30
+ }
31
+ for (const [key, value] of Object.entries(source)) {
32
+ const current = target[key];
33
+ if (current === undefined) {
34
+ target[key] = support_1.util.isPlainObject(value) || Array.isArray(value) ? (0, exports.cloneDeep)(value) : value;
35
+ continue;
36
+ }
37
+ if (support_1.util.isPlainObject(current) && support_1.util.isPlainObject(value)) {
38
+ _defaultsDeep(current, value);
39
+ }
40
+ }
41
+ }
42
+ return target;
43
+ };
44
+ const intersectionWith = (first, second, comparator) => first.filter((item) => second.some((other) => comparator(item, other)));
45
+ exports.intersectionWith = intersectionWith;
46
+ const zip = (arrA, arrB) => {
47
+ const length = Math.max(arrA.length, arrB.length);
48
+ return Array.from({ length }, (_, idx) => [arrA[idx], arrB[idx]]);
49
+ };
50
+ exports.zip = zip;
51
+ const pick = (obj, keysArg) => keysArg.reduce((acc, key) => {
52
+ if (key in obj) {
53
+ acc[key] = obj[key];
54
+ }
55
+ return acc;
56
+ }, {});
57
+ exports.pick = pick;
58
+ const defaultsDeep = (target, ...sources) => _defaultsDeep(target, ...sources);
59
+ exports.defaultsDeep = defaultsDeep;
60
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../../lib/utils/lodash/core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './core';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../lib/utils/lodash/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./core"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/utils/lodash/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yCAAuB"}
package/lib/adb.ts CHANGED
@@ -1,6 +1,4 @@
1
- import _ from 'lodash';
2
1
  import os from 'node:os';
3
- import {DEFAULT_ADB_EXEC_TIMEOUT, requireSdkRoot, getSdkRootFromEnv} from './helpers';
4
2
  import {log} from './logger';
5
3
  import type {ADBOptions, ADBExecutable} from './types';
6
4
  import type {Logcat} from './logcat';
@@ -25,6 +23,14 @@ import * as appCommands from './tools/app-commands';
25
23
  import * as networkCommands from './tools/network-commands';
26
24
  import * as logcatCommands from './tools/logcat-commands';
27
25
  import * as processCommands from './tools/process-commands';
26
+ import {
27
+ DEFAULT_ADB_EXEC_TIMEOUT,
28
+ cloneDeep,
29
+ defaultsDeep,
30
+ getSdkRootFromEnv,
31
+ pick,
32
+ requireSdkRoot,
33
+ } from './utils';
28
34
 
29
35
  export const DEFAULT_ADB_PORT = 5037;
30
36
  export const DEFAULT_OPTS = {
@@ -320,8 +326,8 @@ export class ADB implements ADBOptions {
320
326
  getScreenOrientation = deviceSettingsCommands.getScreenOrientation;
321
327
 
322
328
  constructor(opts: ADBOptions = {} as ADBOptions) {
323
- const options: ADBOptions = _.defaultsDeep(opts, _.cloneDeep(DEFAULT_OPTS));
324
- _.defaultsDeep(this, options);
329
+ const options: ADBOptions = defaultsDeep(opts, cloneDeep(DEFAULT_OPTS));
330
+ defaultsDeep(this, options);
325
331
 
326
332
  // The above defaultsDeep call guarantees the 'executable' field to be always assigned
327
333
  this.executable = options.executable as ADBExecutable;
@@ -372,8 +378,10 @@ export class ADB implements ADBOptions {
372
378
  * @returns The resulting class instance.
373
379
  */
374
380
  clone(opts: ADBOptions = {} as ADBOptions): ADB {
375
- const originalOptions = _.cloneDeep(_.pick(this, Object.keys(DEFAULT_OPTS)));
376
- const cloneOptions = _.defaultsDeep(opts, originalOptions);
381
+ const originalOptions = cloneDeep(pick(this, Object.keys(DEFAULT_OPTS)));
382
+ const cloneOptions = defaultsDeep(opts, originalOptions) as ADBOptions & {
383
+ executable: ADBExecutable;
384
+ };
377
385
 
378
386
  // Reset default arguments created in the constructor.
379
387
  // Without this code, -H and -P can be injected into defaultArgs multiple times.
package/lib/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './adb';
2
2
  export {getAndroidBinaryPath} from './tools/system-calls';
3
- export {getSdkRootFromEnv} from './helpers';
3
+ export {getSdkRootFromEnv} from './utils';
4
4
  export type * from './tools/types';
5
5
  export type * from './types';
6
6
 
package/lib/logcat.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import {logger, util} from '@appium/support';
2
- import _ from 'lodash';
3
2
  import {EventEmitter} from 'node:events';
4
3
  import {SubProcess, exec} from 'teen_process';
5
4
  import {LRUCache} from 'lru-cache';
@@ -148,7 +147,7 @@ export class Logcat extends EventEmitter {
148
147
  result.push(toLogEntry(message, timestamp));
149
148
  }
150
149
  }
151
- if (_.isInteger(recentLogIndex)) {
150
+ if (Number.isInteger(recentLogIndex)) {
152
151
  this.logIndexSinceLastRequest = recentLogIndex;
153
152
  }
154
153
  return result;
@@ -179,12 +178,8 @@ export class Logcat extends EventEmitter {
179
178
 
180
179
  private outputHandler(logLine: string, prefix: string = ''): void {
181
180
  const timestamp = Date.now();
182
- let recentIndex = -1;
183
- for (const key of this.logs.keys()) {
184
- recentIndex = key;
185
- break;
186
- }
187
- this.logs.set(++recentIndex, [logLine, timestamp]);
181
+ const recentIndex = this.logs.keys().next().value ?? -1;
182
+ this.logs.set(recentIndex + 1, [logLine, timestamp]);
188
183
  if (this.listenerCount('output')) {
189
184
  this.emit('output', toLogEntry(logLine, timestamp));
190
185
  }
@@ -225,7 +220,7 @@ function requireSpec(spec: string): string {
225
220
  );
226
221
  return `${resultTag}:${DEFAULT_PRIORITY}`;
227
222
  }
228
- if (!SUPPORTED_PRIORITIES.some((p) => _.toLower(priority) === _.toLower(p))) {
223
+ if (!SUPPORTED_PRIORITIES.some((p) => priority.toLowerCase() === p.toLowerCase())) {
229
224
  log.info(
230
225
  `The priority value in spec '${spec}' is unknown. Supported values are: ${SUPPORTED_PRIORITIES}`,
231
226
  );
@@ -236,11 +231,11 @@ function requireSpec(spec: string): string {
236
231
  }
237
232
 
238
233
  function formatFilterSpecs(filterSpecs: string | string[]): string[] {
239
- if (!_.isArray(filterSpecs)) {
234
+ if (!Array.isArray(filterSpecs)) {
240
235
  filterSpecs = [filterSpecs];
241
236
  }
242
237
  return filterSpecs
243
- .filter((spec) => spec && _.isString(spec) && !spec.startsWith('-'))
238
+ .filter((spec) => spec && typeof spec === 'string' && !spec.startsWith('-'))
244
239
  .map((spec) => (spec.includes(':') ? requireSpec(spec) : spec));
245
240
  }
246
241
 
@@ -2,11 +2,11 @@ import {log} from '../logger';
2
2
  import path from 'node:path';
3
3
  import {fs, tempDir, util} from '@appium/support';
4
4
  import {LRUCache} from 'lru-cache';
5
- import {unzipFile} from '../helpers';
6
5
  import AsyncLock from 'async-lock';
7
6
  import crypto from 'node:crypto';
8
7
  import type {ADB} from '../adb';
9
8
  import type {ApkCreationOptions, StringRecord} from './types';
9
+ import {unzipFile} from '../utils';
10
10
 
11
11
  const AAB_CACHE = new LRUCache<string, string>({
12
12
  max: 10,
@@ -1,11 +1,10 @@
1
- import _ from 'lodash';
2
1
  import {exec} from 'teen_process';
3
2
  import {log} from '../logger';
4
- import {unzipFile, APKS_EXTENSION, readPackageManifest} from '../helpers';
5
3
  import {fs, zip, tempDir, util} from '@appium/support';
6
4
  import path from 'node:path';
7
5
  import type {ADB} from '../adb';
8
6
  import type {APKInfo, PlatformInfo, StringRecord} from './types';
7
+ import {APKS_EXTENSION, readPackageManifest, unzipFile} from '../utils';
9
8
 
10
9
  /**
11
10
  * Extract package and main activity name from application manifest.
@@ -150,6 +149,7 @@ export async function compileManifest(
150
149
  } catch (e1) {
151
150
  throw new Error(
152
151
  `Cannot compile the manifest. Original error: ${(e1 as Error).message || (e1 as {stderr?: string}).stderr}`,
152
+ {cause: e1},
153
153
  );
154
154
  }
155
155
  }
@@ -262,7 +262,7 @@ export async function getAndroidPlatformAndPath(sdkRoot: string): Promise<Platfo
262
262
  platformPath,
263
263
  };
264
264
  }
265
- if (_.isEmpty(platformsMapping)) {
265
+ if (util.isEmpty(platformsMapping)) {
266
266
  log.warn(
267
267
  `Found zero platform folders at '${path.resolve(sdkRoot, 'platforms')}'. ` +
268
268
  `Do you have any Android SDKs installed?`,
@@ -273,7 +273,7 @@ export async function getAndroidPlatformAndPath(sdkRoot: string): Promise<Platfo
273
273
  };
274
274
  }
275
275
 
276
- const recentSdkVersion = _.keys(platformsMapping).sort().reverse()[0];
276
+ const recentSdkVersion = Object.keys(platformsMapping).sort().reverse()[0];
277
277
  const result = platformsMapping[recentSdkVersion];
278
278
  log.debug(`Found the most recent Android platform: ${JSON.stringify(result)}`);
279
279
  return result;
@@ -1,13 +1,12 @@
1
- import _ from 'lodash';
2
1
  import _fs from 'node:fs';
3
2
  import {exec, type ExecError} from 'teen_process';
4
3
  import path from 'node:path';
5
4
  import {log} from '../logger';
6
5
  import {tempDir, system, mkdirp, fs, util, zip} from '@appium/support';
7
6
  import {LRUCache} from 'lru-cache';
8
- import {getJavaForOs, getJavaHome, APKS_EXTENSION, getResourcePath} from '../helpers';
9
7
  import type {ADB} from '../adb';
10
8
  import type {StringRecord, SignedAppCacheValue, CertCheckOptions, KeystoreHash} from './types';
9
+ import {APKS_EXTENSION, getJavaForOs, getJavaHome, getResourcePath} from '../utils';
11
10
 
12
11
  const DEFAULT_PRIVATE_KEY = path.join('keys', 'testkey.pk8');
13
12
  const DEFAULT_CERTIFICATE = path.join('keys', 'testkey.x509.pem');
@@ -45,7 +44,7 @@ export async function executeApksigner(this: ADB, args: string[]): Promise<strin
45
44
  ['stdout', stdout],
46
45
  ['stderr', stderr],
47
46
  ] as const) {
48
- if (!_.trim(stream)) {
47
+ if (!stream?.trim()) {
49
48
  continue;
50
49
  }
51
50
 
@@ -90,6 +89,7 @@ export async function signWithDefaultCert(this: ADB, apk: string): Promise<void>
90
89
  throw new Error(
91
90
  `Could not sign '${apk}' with the default certificate. ` +
92
91
  `Original error: ${err.stderr || err.stdout || err.message}`,
92
+ {cause: e},
93
93
  );
94
94
  }
95
95
  }
@@ -161,6 +161,7 @@ export async function signWithCustomCert(this: ADB, apk: string): Promise<void>
161
161
  throw new Error(
162
162
  `Could not sign with custom certificate. ` +
163
163
  `Original error: ${execErr.stderr || execErr.message}`,
164
+ {cause: e},
164
165
  );
165
166
  }
166
167
  }
@@ -240,6 +241,7 @@ export async function zipAlignApk(this: ADB, apk: string): Promise<boolean> {
240
241
  }
241
242
  throw new Error(
242
243
  `zipAlignApk failed. Original error: ${err.message || (err as ExecError).stderr}`,
244
+ {cause: e},
243
245
  );
244
246
  }
245
247
  }
@@ -270,7 +272,7 @@ export async function checkApkCert(
270
272
  }
271
273
 
272
274
  const hashMatches = (apksignerOutput: string, expectedHashes: KeystoreHash): boolean => {
273
- for (const [name, value] of _.toPairs(expectedHashes)) {
275
+ for (const [name, value] of Object.entries(expectedHashes)) {
274
276
  if (value && new RegExp(`digest:\\s+${value}\\b`, 'i').test(apksignerOutput)) {
275
277
  log.debug(`${name} hash did match for '${path.basename(actualAppPath)}'`);
276
278
  return true;
@@ -321,12 +323,12 @@ export async function checkApkCert(
321
323
  } catch (err) {
322
324
  const error = err as ExecError;
323
325
  // check if there is no signature
324
- if (_.includes(error.stderr, APKSIGNER_VERIFY_FAIL)) {
326
+ if ((error.stderr ?? '').includes(APKSIGNER_VERIFY_FAIL)) {
325
327
  log.info(`'${actualAppPath}' is not signed`);
326
328
  return false;
327
329
  }
328
330
  const errMsg = error.stderr || error.stdout || error.message;
329
- if (_.includes(errMsg, JAVA_PROPS_INIT_ERROR)) {
331
+ if (`${errMsg}`.includes(JAVA_PROPS_INIT_ERROR)) {
330
332
  // This error pops up randomly and we are not quite sure why.
331
333
  // My guess - a race condition in java vm initialization.
332
334
  // Nevertheless, lets make Appium to believe the file is already signed,
@@ -341,6 +343,7 @@ export async function checkApkCert(
341
343
  }
342
344
  throw new Error(
343
345
  `Cannot verify the signature of '${actualAppPath}'. ` + `Original error: ${errMsg}`,
346
+ {cause: err},
344
347
  );
345
348
  }
346
349
  }
@@ -383,7 +386,7 @@ export async function getKeystoreHash(this: ADB): Promise<KeystoreHash> {
383
386
  }
384
387
  result[hashName] = match[1].replace(/:/g, '').toLowerCase();
385
388
  }
386
- if (_.isEmpty(result)) {
389
+ if (util.isEmpty(result)) {
387
390
  log.debug(stdout);
388
391
  throw new Error('Cannot parse the hash value from the keytool output');
389
392
  }
@@ -394,6 +397,7 @@ export async function getKeystoreHash(this: ADB): Promise<KeystoreHash> {
394
397
  throw new Error(
395
398
  `Cannot get the hash of '${this.keystorePath}' keystore. ` +
396
399
  `Original error: ${err.stderr || err.message}`,
400
+ {cause: e},
397
401
  );
398
402
  }
399
403
  }
@@ -1,19 +1,20 @@
1
- import {
2
- APKS_EXTENSION,
3
- buildInstallArgs,
4
- APK_INSTALL_TIMEOUT,
5
- DEFAULT_ADB_EXEC_TIMEOUT,
6
- readPackageManifest,
7
- } from '../helpers';
8
1
  import {exec, type ExecError} from 'teen_process';
9
2
  import {log} from '../logger';
10
3
  import path from 'node:path';
11
- import _ from 'lodash';
12
4
  import {fs, util, mkdirp, timing} from '@appium/support';
13
5
  import * as semver from 'semver';
14
6
  import os from 'node:os';
15
7
  import {LRUCache} from 'lru-cache';
16
8
  import type {ADB} from '../adb';
9
+ import {
10
+ APKS_EXTENSION,
11
+ APK_INSTALL_TIMEOUT,
12
+ DEFAULT_ADB_EXEC_TIMEOUT,
13
+ buildInstallArgs,
14
+ cloneDeep,
15
+ defaults,
16
+ readPackageManifest,
17
+ } from '../utils';
17
18
  import type {
18
19
  UninstallOptions,
19
20
  ShellExecOptions,
@@ -60,7 +61,7 @@ export async function uninstallApk(
60
61
  stdout = (await this.adbExec(cmd, {timeout: options.timeout})).trim();
61
62
  } catch (e) {
62
63
  const err = e as Error;
63
- throw new Error(`Unable to uninstall APK. Original error: ${err.message}`);
64
+ throw new Error(`Unable to uninstall APK. Original error: ${err.message}`, {cause: e});
64
65
  }
65
66
  log.debug(`'adb ${cmd.join(' ')}' command output: ${stdout}`);
66
67
  if (stdout.includes('Success')) {
@@ -111,15 +112,15 @@ export async function cacheApk(
111
112
  let lsOutput: string | null = null;
112
113
  if (
113
114
  this._areExtendedLsOptionsSupported === true ||
114
- !_.isBoolean(this._areExtendedLsOptionsSupported)
115
+ typeof this._areExtendedLsOptionsSupported !== 'boolean'
115
116
  ) {
116
117
  lsOutput = await this.shell([`ls -t -1 ${REMOTE_CACHE_ROOT} 2>&1 || echo ${errorMarker}`]);
117
118
  }
118
119
  if (
119
- !_.isString(lsOutput) ||
120
+ typeof lsOutput !== 'string' ||
120
121
  (lsOutput.includes(errorMarker) && !lsOutput.includes(REMOTE_CACHE_ROOT))
121
122
  ) {
122
- if (!_.isBoolean(this._areExtendedLsOptionsSupported)) {
123
+ if (typeof this._areExtendedLsOptionsSupported !== 'boolean') {
123
124
  log.debug(
124
125
  'The current Android API does not support extended ls options. ' +
125
126
  'Defaulting to no-options call',
@@ -172,9 +173,10 @@ export async function cacheApk(
172
173
  });
173
174
  }
174
175
  // Cleanup the invalid entries from the cache
175
- _.difference([...this.remoteAppsCache.keys()], remoteCachedFiles.map(toHash)).forEach((hash) =>
176
- (this.remoteAppsCache as LRUCache<string, string>).delete(hash),
177
- );
176
+ const remoteCachedHashes = new Set(remoteCachedFiles.map(toHash));
177
+ [...this.remoteAppsCache.keys()]
178
+ .filter((cacheKey) => !remoteCachedHashes.has(cacheKey))
179
+ .forEach((hash) => (this.remoteAppsCache as LRUCache<string, string>).delete(hash));
178
180
  // Bump the cache record for the recently cached item
179
181
  this.remoteAppsCache.set(appHash, remotePath);
180
182
  // If the remote cache exceeds this.remoteAppsCacheLimit, remove the least recently used entries
@@ -182,7 +184,7 @@ export async function cacheApk(
182
184
  .map((x) => path.posix.join(REMOTE_CACHE_ROOT, x))
183
185
  .filter((x) => !(this.remoteAppsCache as LRUCache<string, string>).has(toHash(x)))
184
186
  .slice((this.remoteAppsCacheLimit as number) - [...this.remoteAppsCache.keys()].length);
185
- if (!_.isEmpty(entriesToCleanup)) {
187
+ if (!util.isEmpty(entriesToCleanup)) {
186
188
  try {
187
189
  await this.shell(['rm', '-f', ...entriesToCleanup]);
188
190
  log.debug(`Deleted ${entriesToCleanup.length} expired application cache entries`);
@@ -213,8 +215,8 @@ export async function install(
213
215
  return await this.installApks(appPath, options);
214
216
  }
215
217
 
216
- options = _.cloneDeep(options);
217
- _.defaults(options, {
218
+ options = cloneDeep(options);
219
+ defaults(options, {
218
220
  replace: true,
219
221
  timeout:
220
222
  this.adbExecTimeout === DEFAULT_ADB_EXEC_TIMEOUT ? APK_INSTALL_TIMEOUT : this.adbExecTimeout,
@@ -238,11 +240,7 @@ export async function install(
238
240
  log.info(
239
241
  `The installation of '${path.basename(appPath)}' took ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`,
240
242
  );
241
- const truncatedOutput =
242
- !_.isString(output) || output.length <= 300
243
- ? output
244
- : `${output.substring(0, 150)}...${output.substring(output.length - 150)}`;
245
- log.debug(`Install command stdout: ${truncatedOutput}`);
243
+ log.debug(`Install command stdout: ${util.truncateString(output, {length: 300})}`);
246
244
  if (/\[INSTALL[A-Z_]+FAILED[A-Z_]+\]/.test(output)) {
247
245
  if (this.isTestPackageOnlyError(output)) {
248
246
  const msg = `Set 'allowTestPackages' capability to true in order to allow test packages installation.`;
@@ -302,14 +300,14 @@ export async function getApplicationInstallState(
302
300
  const {versionCode: apkVersionCode, versionName: apkVersionNameStr} = apkInfo || {};
303
301
  const apkVersionName = semver.valid(semver.coerce(apkVersionNameStr));
304
302
 
305
- if (!_.isInteger(apkVersionCode) || !_.isInteger(pkgVersionCode)) {
303
+ if (!Number.isInteger(apkVersionCode) || !Number.isInteger(pkgVersionCode)) {
306
304
  log.warn(`Cannot read version codes of '${appPath}' and/or '${pkg}'`);
307
- if (!_.isString(apkVersionName) || !_.isString(pkgVersionName)) {
305
+ if (typeof apkVersionName !== 'string' || typeof pkgVersionName !== 'string') {
308
306
  log.warn(`Cannot read version names of '${appPath}' and/or '${pkg}'`);
309
307
  return this.APP_INSTALL_STATE.UNKNOWN;
310
308
  }
311
309
  }
312
- if (_.isInteger(apkVersionCode) && _.isInteger(pkgVersionCode)) {
310
+ if (Number.isInteger(apkVersionCode) && Number.isInteger(pkgVersionCode)) {
313
311
  if ((pkgVersionCode as number) > (apkVersionCode as number)) {
314
312
  log.debug(
315
313
  `The version code of the installed '${pkg}' is greater than the application version code (${pkgVersionCode} > ${apkVersionCode})`,
@@ -319,8 +317,8 @@ export async function getApplicationInstallState(
319
317
  // Version codes might not be maintained. Check version names.
320
318
  if (pkgVersionCode === apkVersionCode) {
321
319
  if (
322
- _.isString(apkVersionName) &&
323
- _.isString(pkgVersionName) &&
320
+ typeof apkVersionName === 'string' &&
321
+ typeof pkgVersionName === 'string' &&
324
322
  semver.satisfies(pkgVersionName, `>=${apkVersionName}`)
325
323
  ) {
326
324
  log.debug(
@@ -330,7 +328,7 @@ export async function getApplicationInstallState(
330
328
  ? this.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED
331
329
  : this.APP_INSTALL_STATE.SAME_VERSION_INSTALLED;
332
330
  }
333
- if (!_.isString(apkVersionName) || !_.isString(pkgVersionName)) {
331
+ if (typeof apkVersionName !== 'string' || typeof pkgVersionName !== 'string') {
334
332
  log.debug(
335
333
  `The version name of the installed '${pkg}' is equal to application version name (${pkgVersionCode} === ${apkVersionCode})`,
336
334
  );
@@ -338,8 +336,8 @@ export async function getApplicationInstallState(
338
336
  }
339
337
  }
340
338
  } else if (
341
- _.isString(apkVersionName) &&
342
- _.isString(pkgVersionName) &&
339
+ typeof apkVersionName === 'string' &&
340
+ typeof pkgVersionName === 'string' &&
343
341
  semver.satisfies(pkgVersionName, `>=${apkVersionName}`)
344
342
  ) {
345
343
  log.debug(
@@ -467,7 +465,7 @@ export async function extractStringsFromApk(
467
465
  appPath = await this.extractLanguageApk(appPath, language);
468
466
  }
469
467
 
470
- let apkStrings: StringRecord = {};
468
+ let apkStrings: StringRecord;
471
469
  let configMarker: string;
472
470
  try {
473
471
  await this.initAapt();
@@ -479,7 +477,7 @@ export async function extractStringsFromApk(
479
477
  'configurations',
480
478
  appPath,
481
479
  ]);
482
- return _.uniq(stdout.split(os.EOL));
480
+ return util.uniq(stdout.split(os.EOL));
483
481
  },
484
482
  language,
485
483
  '(default)',
@@ -508,7 +506,7 @@ export async function extractStringsFromApk(
508
506
  'configurations',
509
507
  appPath,
510
508
  ]);
511
- return _.uniq(stdout.split(os.EOL));
509
+ return util.uniq(stdout.split(os.EOL));
512
510
  },
513
511
  language,
514
512
  '',
@@ -525,18 +523,19 @@ export async function extractStringsFromApk(
525
523
  const error = e as Error;
526
524
  throw new Error(
527
525
  `Cannot extract resources from '${originalAppPath}'. ` + `Original error: ${error.message}`,
526
+ {cause: e},
528
527
  );
529
528
  }
530
529
  }
531
530
 
532
- if (_.isEmpty(apkStrings)) {
531
+ if (util.isEmpty(apkStrings)) {
533
532
  log.warn(
534
533
  `No strings have been found in '${originalAppPath}' resources ` +
535
534
  `for '${configMarker || 'default'}' configuration`,
536
535
  );
537
536
  } else {
538
537
  log.info(
539
- `Successfully extracted ${_.keys(apkStrings).length} strings from ` +
538
+ `Successfully extracted ${Object.keys(apkStrings).length} strings from ` +
540
539
  `'${originalAppPath}' resources for '${configMarker || 'default'}' configuration`,
541
540
  );
542
541
  }
@@ -609,10 +608,10 @@ export function parseAapt2Strings(rawOutput: string, configMarker: string): Stri
609
608
  if (startIdx === idx) {
610
609
  return [allLines[idx].substring(startCharPos + 1, terminationCharPos), idx];
611
610
  }
612
- return [`${result}\\n${_.trimStart(allLines[idx].substring(0, terminationCharPos))}`, idx];
611
+ return [`${result}\\n${allLines[idx].substring(0, terminationCharPos).trimStart()}`, idx];
613
612
  }
614
613
  if (idx > startIdx) {
615
- result += `\\n${_.trimStart(allLines[idx])}`;
614
+ result += `\\n${allLines[idx].trimStart()}`;
616
615
  } else {
617
616
  result += allLines[idx].substring(startCharPos + 1);
618
617
  }
@@ -628,7 +627,7 @@ export function parseAapt2Strings(rawOutput: string, configMarker: string): Stri
628
627
  let lineIndex = 0;
629
628
  while (lineIndex < allLines.length) {
630
629
  const trimmedLine = allLines[lineIndex].trim();
631
- if (_.isEmpty(trimmedLine)) {
630
+ if (util.isEmpty(trimmedLine)) {
632
631
  ++lineIndex;
633
632
  continue;
634
633
  }
@@ -672,7 +671,7 @@ export function parseAapt2Strings(rawOutput: string, configMarker: string): Stri
672
671
  if (isInCurrentConfig) {
673
672
  const [content, idx] = extractContent(lineIndex);
674
673
  lineIndex = idx;
675
- if (_.isString(content)) {
674
+ if (typeof content === 'string') {
676
675
  apkStrings[currentResourceId] = [
677
676
  ...(Array.isArray(apkStrings[currentResourceId])
678
677
  ? apkStrings[currentResourceId]
@@ -684,7 +683,7 @@ export function parseAapt2Strings(rawOutput: string, configMarker: string): Stri
684
683
  } else if (trimmedLine.startsWith(`(${configMarker})`)) {
685
684
  const [content, idx] = extractContent(lineIndex);
686
685
  lineIndex = idx;
687
- if (_.isString(content)) {
686
+ if (typeof content === 'string') {
688
687
  apkStrings[currentResourceId] = content;
689
688
  }
690
689
  currentResourceId = null;
@@ -718,7 +717,7 @@ export function parseAaptStrings(rawOutput: string, configMarker: string): Strin
718
717
  const quotedStringPattern = /"[^"\\]*(?:\\.[^"\\]*)*"/;
719
718
  for (const line of rawOutput.split(os.EOL)) {
720
719
  const trimmedLine = line.trim();
721
- if (_.isEmpty(trimmedLine)) {
720
+ if (util.isEmpty(trimmedLine)) {
722
721
  continue;
723
722
  }
724
723
 
@@ -1,13 +1,12 @@
1
1
  import {exec} from 'teen_process';
2
2
  import {log} from '../logger';
3
3
  import path from 'node:path';
4
- import _ from 'lodash';
5
4
  import {fs, tempDir, util} from '@appium/support';
6
5
  import {LRUCache} from 'lru-cache';
7
- import {getJavaForOs, unzipFile, buildInstallArgs, APK_INSTALL_TIMEOUT} from '../helpers';
8
6
  import AsyncLock from 'async-lock';
9
7
  import type {ADB} from '../adb';
10
8
  import type {InstallMultipleApksOptions, InstallApksOptions, StringRecord} from './types';
9
+ import {APK_INSTALL_TIMEOUT, buildInstallArgs, getJavaForOs, unzipFile} from '../utils';
11
10
 
12
11
  const BASE_APK = 'base-master.apk';
13
12
  const LANGUAGE_APK = (lang: string) => `base-${lang}.apk`;
@@ -65,7 +64,7 @@ export async function execBundletool(this: ADB, args: string[], errorMsg: string
65
64
  env,
66
65
  timeout: BUNDLETOOL_TIMEOUT_MS,
67
66
  }));
68
- log.debug(`Command stdout: ${_.truncate(stdout, {length: 300})}`);
67
+ log.debug(`Command stdout: ${util.truncateString(stdout, {length: 300})}`);
69
68
  return stdout;
70
69
  } catch (e) {
71
70
  const err = e as Error & {stdout?: string; stderr?: string};
@@ -75,7 +74,7 @@ export async function execBundletool(this: ADB, args: string[], errorMsg: string
75
74
  if (err.stderr) {
76
75
  log.debug(`Command stderr: ${err.stderr}`);
77
76
  }
78
- throw new Error(`${errorMsg}. Original error: ${err.message}`);
77
+ throw new Error(`${errorMsg}. Original error: ${err.message}`, {cause: e});
79
78
  }
80
79
  }
81
80
 
@@ -240,7 +239,7 @@ export function isTestPackageOnlyError(output: string): boolean {
240
239
  * apks file is not a valid bundle
241
240
  */
242
241
  async function extractFromApks(apks: string, dstPath: string | string[]): Promise<string> {
243
- const normalizedDstPath = _.isArray(dstPath) ? dstPath : [dstPath];
242
+ const normalizedDstPath = Array.isArray(dstPath) ? dstPath : [dstPath];
244
243
 
245
244
  return await APKS_CACHE_GUARD.acquire(apks, async () => {
246
245
  // It might be that the original file has been replaced,