@appium/support 7.1.1 → 7.2.1

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 (70) hide show
  1. package/build/lib/console.d.ts.map +1 -1
  2. package/build/lib/console.js +1 -2
  3. package/build/lib/console.js.map +1 -1
  4. package/build/lib/env.d.ts +12 -5
  5. package/build/lib/env.d.ts.map +1 -1
  6. package/build/lib/env.js +5 -5
  7. package/build/lib/env.js.map +1 -1
  8. package/build/lib/fs.d.ts.map +1 -1
  9. package/build/lib/fs.js +2 -3
  10. package/build/lib/fs.js.map +1 -1
  11. package/build/lib/image-util.d.ts.map +1 -1
  12. package/build/lib/image-util.js +1 -1
  13. package/build/lib/image-util.js.map +1 -1
  14. package/build/lib/index.d.ts +1 -1
  15. package/build/lib/index.d.ts.map +1 -1
  16. package/build/lib/logging.d.ts.map +1 -1
  17. package/build/lib/logging.js +5 -8
  18. package/build/lib/logging.js.map +1 -1
  19. package/build/lib/mjpeg.d.ts.map +1 -1
  20. package/build/lib/mjpeg.js +7 -7
  21. package/build/lib/mjpeg.js.map +1 -1
  22. package/build/lib/net.d.ts.map +1 -1
  23. package/build/lib/net.js +20 -14
  24. package/build/lib/net.js.map +1 -1
  25. package/build/lib/node.d.ts.map +1 -1
  26. package/build/lib/node.js +7 -8
  27. package/build/lib/node.js.map +1 -1
  28. package/build/lib/npm.d.ts.map +1 -1
  29. package/build/lib/npm.js +3 -3
  30. package/build/lib/npm.js.map +1 -1
  31. package/build/lib/plist.js +11 -11
  32. package/build/lib/plist.js.map +1 -1
  33. package/build/lib/process.d.ts.map +1 -1
  34. package/build/lib/process.js +2 -2
  35. package/build/lib/process.js.map +1 -1
  36. package/build/lib/system.d.ts.map +1 -1
  37. package/build/lib/system.js +2 -3
  38. package/build/lib/system.js.map +1 -1
  39. package/build/lib/tempdir.d.ts +3 -2
  40. package/build/lib/tempdir.d.ts.map +1 -1
  41. package/build/lib/tempdir.js +2 -2
  42. package/build/lib/tempdir.js.map +1 -1
  43. package/build/lib/timing.d.ts.map +1 -1
  44. package/build/lib/timing.js +3 -7
  45. package/build/lib/timing.js.map +1 -1
  46. package/build/lib/util.d.ts +80 -1
  47. package/build/lib/util.d.ts.map +1 -1
  48. package/build/lib/util.js +162 -25
  49. package/build/lib/util.js.map +1 -1
  50. package/build/lib/zip.d.ts.map +1 -1
  51. package/build/lib/zip.js +3 -4
  52. package/build/lib/zip.js.map +1 -1
  53. package/lib/console.ts +1 -2
  54. package/lib/env.ts +5 -5
  55. package/lib/fs.ts +6 -4
  56. package/lib/image-util.ts +2 -1
  57. package/lib/index.ts +7 -1
  58. package/lib/logging.ts +5 -5
  59. package/lib/mjpeg.ts +9 -7
  60. package/lib/net.ts +21 -15
  61. package/lib/node.ts +7 -8
  62. package/lib/npm.ts +5 -3
  63. package/lib/plist.ts +11 -11
  64. package/lib/process.ts +8 -2
  65. package/lib/system.ts +2 -3
  66. package/lib/tempdir.ts +2 -2
  67. package/lib/timing.ts +3 -5
  68. package/lib/util.ts +175 -21
  69. package/lib/zip.ts +4 -5
  70. package/package.json +8 -9
package/lib/util.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import B from 'bluebird';
2
- import _ from 'lodash';
2
+ import {randomUUID} from 'node:crypto';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import stream from 'node:stream';
6
- import {promisify} from 'node:util';
6
+ import {isDeepStrictEqual, promisify} from 'node:util';
7
7
  import {asyncmap} from 'asyncbox';
8
8
  import {fs} from './fs';
9
9
  import * as semver from 'semver';
@@ -11,7 +11,7 @@ import {quote as shellQuote, parse as shellParse} from 'shell-quote';
11
11
  export {shellParse};
12
12
  import pluralizeLib from 'pluralize';
13
13
  import {Base64Encode} from 'base64-stream';
14
- export {v1 as uuidV1, v3 as uuidV3, v4 as uuidV4, v5 as uuidV5} from 'uuid';
14
+ import {v1 as uuidV1Lib, v3 as uuidV3Lib, v5 as uuidV5Lib} from 'uuid';
15
15
  import * as _lockfile from 'lockfile';
16
16
  import type {Element} from '@appium/types';
17
17
 
@@ -28,6 +28,36 @@ export const GiB = MiB * 1024;
28
28
  /** A string which is never `''`. */
29
29
  export type NonEmptyString<T extends string = string> = T extends '' ? never : T;
30
30
 
31
+ /**
32
+ * @deprecated This helper is slated for removal. Please migrate callers away from UUID v1.
33
+ */
34
+ export function uuidV1(...args: Parameters<typeof uuidV1Lib>): ReturnType<typeof uuidV1Lib> {
35
+ return uuidV1Lib(...args);
36
+ }
37
+
38
+ /**
39
+ * @deprecated This helper is slated for removal. Please migrate callers away from UUID v3.
40
+ */
41
+ export function uuidV3(...args: Parameters<typeof uuidV3Lib>): ReturnType<typeof uuidV3Lib> {
42
+ return uuidV3Lib(...args);
43
+ }
44
+
45
+ /**
46
+ * Generates a v4 UUID using Node.js crypto.
47
+ *
48
+ * @returns A UUID v4 string
49
+ */
50
+ export function uuidV4(): string {
51
+ return randomUUID();
52
+ }
53
+
54
+ /**
55
+ * @deprecated This helper is slated for removal. Please migrate callers away from UUID v5.
56
+ */
57
+ export function uuidV5(...args: Parameters<typeof uuidV5Lib>): ReturnType<typeof uuidV5Lib> {
58
+ return uuidV5Lib(...args);
59
+ }
60
+
31
61
  /**
32
62
  * Type guard: returns true if the value is a non-empty string.
33
63
  *
@@ -35,7 +65,7 @@ export type NonEmptyString<T extends string = string> = T extends '' ? never : T
35
65
  * @returns `true` if `val` is a string with at least one character
36
66
  */
37
67
  export function hasContent(val: unknown): val is NonEmptyString {
38
- return _.isString(val) && val !== '';
68
+ return typeof val === 'string' && val !== '';
39
69
  }
40
70
 
41
71
  /**
@@ -45,10 +75,124 @@ export function hasContent(val: unknown): val is NonEmptyString {
45
75
  * @returns `true` if `val` is non-null and non-undefined (and not NaN for numbers)
46
76
  */
47
77
  export function hasValue<T>(val: T): val is NonNullable<T> {
48
- if (_.isNumber(val)) {
49
- return !_.isNaN(val);
78
+ if (typeof val === 'number') {
79
+ return !Number.isNaN(val);
80
+ }
81
+ return val !== undefined && val !== null;
82
+ }
83
+
84
+ /**
85
+ * Creates a memoized version of a function.
86
+ *
87
+ * @param fn - Function to memoize
88
+ * @param resolver - Optional cache key resolver. If omitted, the first argument is used as the cache key.
89
+ * @returns Memoized function with a mutable `.cache` map (compatible with lodash-style cache resets in tests).
90
+ */
91
+ export function memoize<Fn extends (...args: any[]) => any>(
92
+ fn: Fn,
93
+ resolver?: (...args: Parameters<Fn>) => unknown
94
+ ): Fn & {cache: Map<unknown, ReturnType<Fn>>} {
95
+ const memoizedFn = (function (this: unknown, ...args: Parameters<Fn>) {
96
+ const key = resolver ? resolver.apply(this, args) : args[0];
97
+ if (memoizedFn.cache.has(key)) {
98
+ return memoizedFn.cache.get(key) as ReturnType<Fn>;
99
+ }
100
+ const result = fn.apply(this, args);
101
+ memoizedFn.cache.set(key, result);
102
+ return result;
103
+ }) as unknown as Fn & {cache: Map<unknown, ReturnType<Fn>>};
104
+ memoizedFn.cache = new Map<unknown, ReturnType<Fn>>();
105
+ return memoizedFn;
106
+ }
107
+
108
+ /**
109
+ * Returns true if the value is a plain object (Object prototype or null prototype).
110
+ *
111
+ * @param value - Value to check
112
+ * @returns `true` if the value is a plain object
113
+ */
114
+ export function isPlainObject(value: unknown): value is Record<string, unknown> {
115
+ if (value === null || typeof value !== 'object') {
116
+ return false;
117
+ }
118
+ const prototype = Object.getPrototypeOf(value);
119
+ return prototype === null || prototype === Object.prototype;
120
+ }
121
+
122
+ /**
123
+ * Returns true when the value has no elements/properties.
124
+ *
125
+ * @param value - Value to check
126
+ * @returns `true` if the value is empty
127
+ */
128
+ export function isEmpty(value: unknown): boolean {
129
+ if (value == null) {
130
+ return true;
50
131
  }
51
- return !_.isUndefined(val) && !_.isNull(val);
132
+ if (typeof value === 'string' || Array.isArray(value) || Buffer.isBuffer(value)) {
133
+ return value.length === 0;
134
+ }
135
+ if (value instanceof Map || value instanceof Set) {
136
+ return value.size === 0;
137
+ }
138
+ if (typeof value === 'object' || typeof value === 'function') {
139
+ return Object.keys(value).length === 0;
140
+ }
141
+ return true;
142
+ }
143
+
144
+ /**
145
+ * Performs a deep equality check between two values.
146
+ *
147
+ * @param left - First value
148
+ * @param right - Second value
149
+ * @returns `true` when values are deeply equal
150
+ */
151
+ export function isEqual(left: unknown, right: unknown): boolean {
152
+ return isDeepStrictEqual(left, right);
153
+ }
154
+
155
+ /**
156
+ * Escapes RegExp special characters in a string.
157
+ *
158
+ * @param value - Input string
159
+ * @returns Escaped string safe for RegExp source
160
+ */
161
+ export function escapeRegExp(value: string): string {
162
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
163
+ }
164
+
165
+ /**
166
+ * Returns a duplicate-free copy of the input array.
167
+ *
168
+ * @param values - Input array
169
+ * @returns New array with unique values preserving input order
170
+ */
171
+ export function uniq<T>(values: readonly T[]): T[] {
172
+ return [...new Set(values)];
173
+ }
174
+
175
+ /**
176
+ * Truncates a string to a maximum length.
177
+ *
178
+ * @param value - Input string
179
+ * @param options - Truncation options or max length
180
+ * @returns Truncated string
181
+ */
182
+ export function truncateString(value: string, options: TruncateStringOptions | number = {}): string {
183
+ const normalizedOptions = typeof options === 'number' ? {length: options} : options;
184
+ const {length, omission = '…'} = normalizedOptions;
185
+ const stringValue =
186
+ value == null ? '' : typeof value === 'number' && Object.is(value, -0) ? '-0' : String(value);
187
+ const maxLength = length ?? 30;
188
+ if (maxLength <= 0) {
189
+ return omission;
190
+ }
191
+ if (stringValue.length <= maxLength) {
192
+ return stringValue;
193
+ }
194
+ const contentLength = maxLength - omission.length;
195
+ return contentLength > 0 ? `${stringValue.slice(0, contentLength)}${omission}` : omission;
52
196
  }
53
197
 
54
198
  /**
@@ -177,7 +321,7 @@ export function jsonStringify(
177
321
  replacer: ((key: string, value: unknown) => unknown) | null = null,
178
322
  space: number | string = 2
179
323
  ): string {
180
- const replacerFunc = _.isFunction(replacer) ? replacer : (_k: string, v: unknown) => v;
324
+ const replacerFunc = typeof replacer === 'function' ? replacer : (_k: string, v: unknown) => v;
181
325
 
182
326
  const bufferToJSON = Buffer.prototype.toJSON;
183
327
  delete (Buffer.prototype as Record<string, unknown>).toJSON;
@@ -202,10 +346,11 @@ export function jsonStringify(
202
346
  * @returns The element ID string
203
347
  */
204
348
  export function unwrapElement(el: Element | string): string {
205
- const elObj = el as unknown as Record<string, string>;
206
- for (const propName of [W3C_WEB_ELEMENT_IDENTIFIER, 'ELEMENT']) {
207
- if (_.has(elObj, propName)) {
208
- return elObj[propName];
349
+ if (isPlainObject(el)) {
350
+ for (const propName of [W3C_WEB_ELEMENT_IDENTIFIER, 'ELEMENT']) {
351
+ if (Object.hasOwn(el, propName)) {
352
+ return el[propName] as string;
353
+ }
209
354
  }
210
355
  }
211
356
  return el as string;
@@ -238,11 +383,11 @@ export function filterObject<T extends Record<string, unknown>>(
238
383
  obj: T,
239
384
  predicate?: ((value: unknown, obj: T) => boolean) | unknown
240
385
  ): Partial<T> {
241
- const newObj = _.clone(obj) as Record<string, unknown>;
386
+ const newObj = {...obj} as Record<string, unknown>;
242
387
  let pred: (v: unknown, o: T) => boolean;
243
- if (_.isUndefined(predicate)) {
244
- pred = (v) => !_.isUndefined(v);
245
- } else if (!_.isFunction(predicate)) {
388
+ if (predicate === undefined) {
389
+ pred = (v) => v !== undefined;
390
+ } else if (typeof predicate !== 'function') {
246
391
  const valuePredicate = predicate;
247
392
  pred = (v) => v === valuePredicate;
248
393
  } else {
@@ -374,6 +519,14 @@ export interface LockFileOptions {
374
519
  tryRecovery?: boolean;
375
520
  }
376
521
 
522
+ /** Options for truncateString(). */
523
+ export interface TruncateStringOptions {
524
+ /** Maximum length of the resulting string. Default 30. */
525
+ length?: number;
526
+ /** Suffix appended to truncated strings. Default "…". */
527
+ omission?: string;
528
+ }
529
+
377
530
  /** Guard function that runs the given behavior under the lock. */
378
531
  type LockFileGuardFn<T> = (behavior: () => Promise<T> | T) => Promise<T>;
379
532
 
@@ -415,7 +568,7 @@ export function compareVersions(
415
568
  * @returns Quoted string suitable for shell parsing
416
569
  */
417
570
  export function quote(args: string | string[]): string {
418
- return shellQuote(_.castArray(args));
571
+ return shellQuote(Array.isArray(args) ? args : [args]);
419
572
  }
420
573
 
421
574
  /**
@@ -432,9 +585,9 @@ export function pluralize(
432
585
  options: PluralizeOptions | boolean = {}
433
586
  ): string {
434
587
  let inclusive = false;
435
- if (_.isBoolean(options)) {
588
+ if (typeof options === 'boolean') {
436
589
  inclusive = options;
437
- } else if (_.isBoolean(options?.inclusive)) {
590
+ } else if (typeof options?.inclusive === 'boolean') {
438
591
  inclusive = options.inclusive;
439
592
  }
440
593
  return pluralizeLib(word, count, inclusive);
@@ -537,13 +690,14 @@ export function getLockFileGuard<T>(
537
690
  acquired = true;
538
691
  } catch (e) {
539
692
  const err = e as Error;
540
- if (_.includes(err.message, 'EEXIST') && tryRecovery && !triedRecovery) {
693
+ if (err.message?.includes('EEXIST') && tryRecovery && !triedRecovery) {
541
694
  _lockfile.unlockSync(lockFile);
542
695
  triedRecovery = true;
543
696
  } else {
544
697
  throw new Error(
545
698
  `Could not acquire lock on '${lockFile}' after ${timeout}s. ` +
546
- `Original error: ${err.message}`
699
+ `Original error: ${err.message}`,
700
+ {cause: e}
547
701
  );
548
702
  }
549
703
  }
package/lib/zip.ts CHANGED
@@ -1,4 +1,3 @@
1
- import _ from 'lodash';
2
1
  import {promisify} from 'node:util';
3
2
  import * as yauzl from 'yauzl';
4
3
  import archiver from 'archiver';
@@ -9,7 +8,7 @@ import {pipeline} from 'node:stream/promises';
9
8
  import {fs} from './fs';
10
9
  import {isWindows} from './system';
11
10
  import {Base64Encode} from 'base64-stream';
12
- import {isSubPath, toReadableSizeString, GiB} from './util';
11
+ import {isSubPath, memoize, toReadableSizeString, GiB} from './util';
13
12
  import {Timer} from './timing';
14
13
  import log from './logger';
15
14
  import getStream from 'get-stream';
@@ -554,8 +553,8 @@ async function extractWithSystemUnzip(zipFilePath: string, destDir: string): Pro
554
553
  let executablePath: string;
555
554
  try {
556
555
  executablePath = await getExecutablePath(isWindowsHost ? 'powershell.exe' : 'unzip');
557
- } catch {
558
- throw new Error('Could not find system unzip');
556
+ } catch (e) {
557
+ throw new Error('Could not find system unzip', {cause: e});
559
558
  }
560
559
 
561
560
  if (isWindowsHost) {
@@ -581,7 +580,7 @@ async function extractWithSystemUnzip(zipFilePath: string, destDir: string): Pro
581
580
  * Finds and memoizes the full path to the given executable.
582
581
  * Rejects if it is not found.
583
582
  */
584
- const getExecutablePath = _.memoize(
583
+ const getExecutablePath = memoize(
585
584
  /**
586
585
  * @returns Full Path to the executable
587
586
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appium/support",
3
- "version": "7.1.1",
3
+ "version": "7.2.1",
4
4
  "description": "Support libs used across Appium packages",
5
5
  "keywords": [
6
6
  "automation",
@@ -42,26 +42,25 @@
42
42
  "dependencies": {
43
43
  "@appium/logger": "2.0.7",
44
44
  "@appium/tsconfig": "1.1.2",
45
- "@appium/types": "1.3.1",
45
+ "@appium/types": "1.4.0",
46
46
  "@colors/colors": "1.6.0",
47
47
  "archiver": "7.0.1",
48
- "asyncbox": "6.1.0",
49
- "axios": "1.15.0",
48
+ "asyncbox": "6.2.0",
49
+ "axios": "1.16.0",
50
50
  "base64-stream": "1.0.0",
51
51
  "bluebird": "3.7.2",
52
52
  "bplist-creator": "0.1.1",
53
53
  "bplist-parser": "0.3.2",
54
54
  "form-data": "4.0.5",
55
55
  "get-stream": "9.0.1",
56
- "glob": "13.0.6",
56
+ "glob": "13.0.5",
57
57
  "jsftp": "2.1.3",
58
58
  "klaw": "4.1.0",
59
59
  "lockfile": "1.0.4",
60
- "lodash": "4.18.1",
61
60
  "log-symbols": "7.0.1",
62
61
  "ncp": "2.0.0",
63
62
  "package-directory": "8.2.0",
64
- "plist": "3.1.0",
63
+ "plist": "4.0.0",
65
64
  "pluralize": "8.0.0",
66
65
  "read-pkg": "10.1.0",
67
66
  "resolve-from": "5.0.0",
@@ -69,7 +68,7 @@
69
68
  "semver": "7.7.4",
70
69
  "shell-quote": "1.8.3",
71
70
  "supports-color": "10.2.2",
72
- "teen_process": "4.1.1",
71
+ "teen_process": "4.1.3",
73
72
  "type-fest": "5.6.0",
74
73
  "uuid": "14.0.0",
75
74
  "which": "6.0.1",
@@ -85,5 +84,5 @@
85
84
  "publishConfig": {
86
85
  "access": "public"
87
86
  },
88
- "gitHead": "17f84265d10944fec06ae7684ae8ad77d1224b50"
87
+ "gitHead": "fd6dbe9eff4b52bd5436811ae71b0425c0ebfff4"
89
88
  }