appium 3.5.1 → 3.6.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 (208) hide show
  1. package/build/lib/appium.d.ts +3 -4
  2. package/build/lib/appium.d.ts.map +1 -1
  3. package/build/lib/appium.js +10 -19
  4. package/build/lib/appium.js.map +1 -1
  5. package/build/lib/bidi-commands.d.ts +2 -2
  6. package/build/lib/bidi-commands.d.ts.map +1 -1
  7. package/build/lib/bidi-commands.js +4 -4
  8. package/build/lib/bidi-commands.js.map +1 -1
  9. package/build/lib/bootstrap/appium-initializer.d.ts.map +1 -1
  10. package/build/lib/bootstrap/appium-initializer.js +12 -16
  11. package/build/lib/bootstrap/appium-initializer.js.map +1 -1
  12. package/build/lib/bootstrap/appium-main-runner.d.ts +1 -1
  13. package/build/lib/bootstrap/appium-main-runner.d.ts.map +1 -1
  14. package/build/lib/bootstrap/appium-main-runner.js +2 -2
  15. package/build/lib/bootstrap/appium-main-runner.js.map +1 -1
  16. package/build/lib/bootstrap/config-file.d.ts +1 -1
  17. package/build/lib/bootstrap/config-file.d.ts.map +1 -1
  18. package/build/lib/bootstrap/config-file.js +13 -15
  19. package/build/lib/bootstrap/config-file.js.map +1 -1
  20. package/build/lib/bootstrap/grid-v3-register.d.ts.map +1 -1
  21. package/build/lib/bootstrap/grid-v3-register.js +7 -14
  22. package/build/lib/bootstrap/grid-v3-register.js.map +1 -1
  23. package/build/lib/bootstrap/init-types.d.ts +1 -1
  24. package/build/lib/bootstrap/init-types.d.ts.map +1 -1
  25. package/build/lib/bootstrap/main-helpers.d.ts +1 -1
  26. package/build/lib/bootstrap/main-helpers.d.ts.map +1 -1
  27. package/build/lib/bootstrap/main-helpers.js +5 -6
  28. package/build/lib/bootstrap/main-helpers.js.map +1 -1
  29. package/build/lib/bootstrap/node-helpers.d.ts +1 -1
  30. package/build/lib/bootstrap/node-helpers.d.ts.map +1 -1
  31. package/build/lib/bootstrap/node-helpers.js +6 -8
  32. package/build/lib/bootstrap/node-helpers.js.map +1 -1
  33. package/build/lib/bootstrap/startup-config.d.ts.map +1 -1
  34. package/build/lib/bootstrap/startup-config.js.map +1 -1
  35. package/build/lib/cli/args.d.ts +2 -4
  36. package/build/lib/cli/args.d.ts.map +1 -1
  37. package/build/lib/cli/args.js +3 -6
  38. package/build/lib/cli/args.js.map +1 -1
  39. package/build/lib/cli/driver-command.d.ts +2 -2
  40. package/build/lib/cli/driver-command.d.ts.map +1 -1
  41. package/build/lib/cli/driver-command.js +4 -7
  42. package/build/lib/cli/driver-command.js.map +1 -1
  43. package/build/lib/cli/extension-command.d.ts +3 -20
  44. package/build/lib/cli/extension-command.d.ts.map +1 -1
  45. package/build/lib/cli/extension-command.js +32 -56
  46. package/build/lib/cli/extension-command.js.map +1 -1
  47. package/build/lib/cli/extension.d.ts.map +1 -1
  48. package/build/lib/cli/extension.js.map +1 -1
  49. package/build/lib/cli/parser.d.ts.map +1 -1
  50. package/build/lib/cli/parser.js +10 -15
  51. package/build/lib/cli/parser.js.map +1 -1
  52. package/build/lib/cli/plugin-command.d.ts +2 -2
  53. package/build/lib/cli/plugin-command.d.ts.map +1 -1
  54. package/build/lib/cli/plugin-command.js +4 -7
  55. package/build/lib/cli/plugin-command.js.map +1 -1
  56. package/build/lib/cli/setup-command.d.ts.map +1 -1
  57. package/build/lib/cli/setup-command.js +2 -2
  58. package/build/lib/cli/setup-command.js.map +1 -1
  59. package/build/lib/cli/utils.d.ts.map +1 -1
  60. package/build/lib/cli/utils.js.map +1 -1
  61. package/build/lib/doctor/doctor.d.ts.map +1 -1
  62. package/build/lib/doctor/doctor.js +1 -4
  63. package/build/lib/doctor/doctor.js.map +1 -1
  64. package/build/lib/extension/driver-config.d.ts +1 -1
  65. package/build/lib/extension/driver-config.d.ts.map +1 -1
  66. package/build/lib/extension/driver-config.js +2 -4
  67. package/build/lib/extension/driver-config.js.map +1 -1
  68. package/build/lib/extension/extension-config.d.ts +1 -1
  69. package/build/lib/extension/extension-config.d.ts.map +1 -1
  70. package/build/lib/extension/extension-config.js +10 -10
  71. package/build/lib/extension/extension-config.js.map +1 -1
  72. package/build/lib/extension/index.d.ts.map +1 -1
  73. package/build/lib/extension/index.js +3 -5
  74. package/build/lib/extension/index.js.map +1 -1
  75. package/build/lib/extension/manifest-migrations.d.ts.map +1 -1
  76. package/build/lib/extension/manifest-migrations.js.map +1 -1
  77. package/build/lib/extension/manifest.d.ts.map +1 -1
  78. package/build/lib/extension/manifest.js +2 -2
  79. package/build/lib/extension/manifest.js.map +1 -1
  80. package/build/lib/extension/plugin-config.d.ts.map +1 -1
  81. package/build/lib/extension/plugin-config.js +1 -2
  82. package/build/lib/extension/plugin-config.js.map +1 -1
  83. package/build/lib/helpers/build.d.ts.map +1 -1
  84. package/build/lib/helpers/build.js +1 -1
  85. package/build/lib/helpers/build.js.map +1 -1
  86. package/build/lib/helpers/capability.d.ts.map +1 -1
  87. package/build/lib/helpers/capability.js +2 -4
  88. package/build/lib/helpers/capability.js.map +1 -1
  89. package/build/lib/helpers/network.d.ts.map +1 -1
  90. package/build/lib/helpers/network.js +1 -3
  91. package/build/lib/helpers/network.js.map +1 -1
  92. package/build/lib/insecure-features.d.ts +1 -1
  93. package/build/lib/insecure-features.d.ts.map +1 -1
  94. package/build/lib/insecure-features.js +2 -6
  95. package/build/lib/insecure-features.js.map +1 -1
  96. package/build/lib/inspector-commands.d.ts.map +1 -1
  97. package/build/lib/inspector-commands.js +6 -16
  98. package/build/lib/inspector-commands.js.map +1 -1
  99. package/build/lib/logsink.d.ts.map +1 -1
  100. package/build/lib/logsink.js +5 -9
  101. package/build/lib/logsink.js.map +1 -1
  102. package/build/lib/main.d.ts.map +1 -1
  103. package/build/lib/main.js.map +1 -1
  104. package/build/lib/schema/arg-spec.d.ts.map +1 -1
  105. package/build/lib/schema/arg-spec.js.map +1 -1
  106. package/build/lib/schema/cli-args-guards.d.ts +1 -1
  107. package/build/lib/schema/cli-args-guards.d.ts.map +1 -1
  108. package/build/lib/schema/cli-args-guards.js.map +1 -1
  109. package/build/lib/schema/cli-args.d.ts.map +1 -1
  110. package/build/lib/schema/cli-args.js +2 -2
  111. package/build/lib/schema/cli-args.js.map +1 -1
  112. package/build/lib/schema/cli-transformers.d.ts.map +1 -1
  113. package/build/lib/schema/cli-transformers.js +2 -4
  114. package/build/lib/schema/cli-transformers.js.map +1 -1
  115. package/build/lib/schema/format-errors.d.ts +1 -1
  116. package/build/lib/schema/format-errors.d.ts.map +1 -1
  117. package/build/lib/schema/format-errors.js.map +1 -1
  118. package/build/lib/schema/index.d.ts +2 -2
  119. package/build/lib/schema/index.d.ts.map +1 -1
  120. package/build/lib/schema/index.js +2 -2
  121. package/build/lib/schema/index.js.map +1 -1
  122. package/build/lib/schema/keywords.d.ts.map +1 -1
  123. package/build/lib/schema/keywords.js.map +1 -1
  124. package/build/lib/schema/schema.d.ts +1 -1
  125. package/build/lib/schema/schema.d.ts.map +1 -1
  126. package/build/lib/schema/schema.js +5 -7
  127. package/build/lib/schema/schema.js.map +1 -1
  128. package/build/lib/utils/index.d.ts +2 -2
  129. package/build/lib/utils/index.d.ts.map +1 -1
  130. package/build/lib/utils/index.js +8 -8
  131. package/build/lib/utils/index.js.map +1 -1
  132. package/build/lib/utils/is-package-changed.d.ts.map +1 -1
  133. package/build/lib/utils/is-package-changed.js +2 -4
  134. package/build/lib/utils/is-package-changed.js.map +1 -1
  135. package/build/lib/utils/object.d.ts.map +1 -1
  136. package/build/lib/utils/object.js +1 -3
  137. package/build/lib/utils/object.js.map +1 -1
  138. package/build/lib/utils/package-changed.d.ts +0 -1
  139. package/build/lib/utils/package-changed.d.ts.map +1 -1
  140. package/build/lib/utils/package-changed.js +4 -3
  141. package/build/lib/utils/package-changed.js.map +1 -1
  142. package/build/lib/utils/package-json.d.ts.map +1 -1
  143. package/build/lib/utils/package-json.js.map +1 -1
  144. package/build/lib/utils/resolve-from.d.ts.map +1 -1
  145. package/build/lib/utils/resolve-from.js.map +1 -1
  146. package/build/types/cli.d.ts.map +1 -1
  147. package/build/types/index.d.ts +2 -2
  148. package/build/types/index.d.ts.map +1 -1
  149. package/build/types/index.js +1 -1
  150. package/build/types/index.js.map +1 -1
  151. package/build/types/manifest/base.d.ts.map +1 -1
  152. package/build/types/manifest/v3.d.ts.map +1 -1
  153. package/build/types/manifest/v4.d.ts.map +1 -1
  154. package/lib/appium.ts +46 -94
  155. package/lib/bidi-commands.ts +28 -63
  156. package/lib/bootstrap/appium-initializer.ts +26 -38
  157. package/lib/bootstrap/appium-main-runner.ts +14 -32
  158. package/lib/bootstrap/config-file.ts +19 -37
  159. package/lib/bootstrap/grid-v3-register.ts +12 -38
  160. package/lib/bootstrap/init-types.ts +3 -5
  161. package/lib/bootstrap/main-helpers.ts +15 -25
  162. package/lib/bootstrap/node-helpers.ts +11 -22
  163. package/lib/bootstrap/startup-config.ts +13 -18
  164. package/lib/cli/args.ts +9 -18
  165. package/lib/cli/driver-command.ts +6 -13
  166. package/lib/cli/extension-command.ts +55 -156
  167. package/lib/cli/extension.ts +6 -5
  168. package/lib/cli/parser.ts +23 -29
  169. package/lib/cli/plugin-command.ts +7 -17
  170. package/lib/cli/setup-command.ts +10 -28
  171. package/lib/cli/utils.ts +1 -5
  172. package/lib/doctor/doctor.ts +1 -4
  173. package/lib/extension/driver-config.ts +5 -15
  174. package/lib/extension/extension-config.ts +36 -80
  175. package/lib/extension/index.ts +16 -31
  176. package/lib/extension/manifest-migrations.ts +1 -0
  177. package/lib/extension/manifest.ts +9 -19
  178. package/lib/extension/plugin-config.ts +5 -12
  179. package/lib/helpers/build.ts +4 -6
  180. package/lib/helpers/capability.ts +6 -17
  181. package/lib/helpers/network.ts +2 -6
  182. package/lib/insecure-features.ts +7 -22
  183. package/lib/inspector-commands.ts +28 -68
  184. package/lib/logsink.ts +11 -25
  185. package/lib/main.ts +2 -7
  186. package/lib/schema/arg-spec.ts +1 -0
  187. package/lib/schema/cli-args-guards.ts +7 -14
  188. package/lib/schema/cli-args.ts +10 -17
  189. package/lib/schema/cli-transformers.ts +5 -10
  190. package/lib/schema/format-errors.ts +2 -1
  191. package/lib/schema/index.ts +2 -2
  192. package/lib/schema/keywords.ts +2 -2
  193. package/lib/schema/schema.ts +14 -33
  194. package/lib/utils/index.ts +3 -3
  195. package/lib/utils/is-package-changed.ts +4 -7
  196. package/lib/utils/object.ts +4 -13
  197. package/lib/utils/package-changed.ts +7 -9
  198. package/lib/utils/package-json.ts +2 -3
  199. package/lib/utils/resolve-from.ts +1 -4
  200. package/package.json +32 -31
  201. package/scripts/autoinstall-extensions.js +1 -4
  202. package/tsconfig.json +7 -11
  203. package/types/cli.ts +2 -3
  204. package/types/index.ts +2 -2
  205. package/types/manifest/base.ts +3 -10
  206. package/types/manifest/v3.ts +3 -10
  207. package/types/manifest/v4.ts +3 -10
  208. package/LICENSE +0 -201
@@ -1,5 +1,8 @@
1
- import {asyncfilter, asyncmap} from 'asyncbox';
1
+ import {spawn} from 'node:child_process';
2
2
  import path from 'node:path';
3
+ import {pathToFileURL} from 'node:url';
4
+ import {inspect} from 'node:util';
5
+
3
6
  import {console, env, fs, npm, system, util} from '@appium/support';
4
7
  import type {AppiumLogger, ExtensionType, IDoctorCheck} from '@appium/types';
5
8
  import type {
@@ -10,23 +13,22 @@ import type {
10
13
  ExtRecord as AppiumExtRecord,
11
14
  InstallType,
12
15
  } from 'appium/types';
16
+ import {asyncfilter, asyncmap} from 'asyncbox';
17
+ import * as semver from 'semver';
18
+ import {SubProcess} from 'teen_process';
13
19
  import type {PackageJson} from 'type-fest';
20
+
21
+ import {Doctor, EXIT_CODE as DOCTOR_EXIT_CODE} from '../doctor/doctor';
14
22
  import type {ExtensionConfig as BaseExtensionConfig} from '../extension/extension-config';
15
- import {spinWith, RingBuffer} from './utils';
16
23
  import {
17
- INSTALL_TYPE_NPM,
24
+ INSTALL_TYPE_DEV,
18
25
  INSTALL_TYPE_GIT,
19
26
  INSTALL_TYPE_GITHUB,
20
27
  INSTALL_TYPE_LOCAL,
21
- INSTALL_TYPE_DEV,
28
+ INSTALL_TYPE_NPM,
22
29
  } from '../extension/extension-config';
23
- import {SubProcess} from 'teen_process';
24
- import {spawn} from 'node:child_process';
25
- import {inspect} from 'node:util';
26
- import {pathToFileURL} from 'node:url';
27
- import {Doctor, EXIT_CODE as DOCTOR_EXIT_CODE} from '../doctor/doctor';
28
30
  import {appiumPackageRoot, compact, npmPackage, packageDidChange} from '../utils';
29
- import * as semver from 'semver';
31
+ import {RingBuffer, spinWith} from './utils';
30
32
 
31
33
  const UPDATE_ALL = 'installed';
32
34
  const MAX_CONCURRENT_REPO_FETCHES = 5;
@@ -38,17 +40,14 @@ export type ExtensionCommandOptions<ExtType extends ExtensionType = ExtensionTyp
38
40
  config: ExtensionConfig<ExtType>;
39
41
  json: boolean;
40
42
  };
41
- export type ExtensionConfig<ExtType extends ExtensionType = ExtensionType> =
42
- BaseExtensionConfig<ExtType>;
43
+ export type ExtensionConfig<ExtType extends ExtensionType = ExtensionType> = BaseExtensionConfig<ExtType>;
43
44
 
44
45
  export type ExtRecord<ExtType extends ExtensionType = ExtensionType> = AppiumExtRecord<ExtType>;
45
46
 
46
47
  export type ExtMetadata<ExtType extends ExtensionType = ExtensionType> = AppiumExtMetadata<ExtType>;
47
48
  export type ExtManifest<ExtType extends ExtensionType = ExtensionType> = AppiumExtManifest<ExtType>;
48
- export type ExtPackageJson<ExtType extends ExtensionType = ExtensionType> =
49
- AppiumExtPackageJson<ExtType>;
50
- export type ExtInstallReceipt<ExtType extends ExtensionType = ExtensionType> =
51
- AppiumExtInstallReceipt<ExtType>;
49
+ export type ExtPackageJson<ExtType extends ExtensionType = ExtensionType> = AppiumExtPackageJson<ExtType>;
50
+ export type ExtInstallReceipt<ExtType extends ExtensionType = ExtensionType> = AppiumExtInstallReceipt<ExtType>;
52
51
  /**
53
52
  * Extra stuff about extensions; used indirectly by {@linkcode ExtensionCliCommand.list}.
54
53
  */
@@ -64,21 +63,16 @@ export type ExtensionListMetadata = {
64
63
  /**
65
64
  * Possible return value for {@linkcode ExtensionCliCommand.list}
66
65
  */
67
- export type ExtensionListData<ExtType extends ExtensionType = ExtensionType> = Partial<
68
- ExtManifest<ExtType>
69
- > &
66
+ export type ExtensionListData<ExtType extends ExtensionType = ExtensionType> = Partial<ExtManifest<ExtType>> &
70
67
  Partial<ExtensionListMetadata>;
71
68
 
72
- export type InstalledExtensionListData<ExtType extends ExtensionType = ExtensionType> =
73
- ExtManifest<ExtType> & ExtensionListMetadata;
69
+ export type InstalledExtensionListData<ExtType extends ExtensionType = ExtensionType> = ExtManifest<ExtType> &
70
+ ExtensionListMetadata;
74
71
 
75
72
  /**
76
73
  * Return value of {@linkcode ExtensionCliCommand.list}.
77
74
  */
78
- export type ExtensionList<ExtType extends ExtensionType = ExtensionType> = Record<
79
- string,
80
- ExtensionListData<ExtType>
81
- >;
75
+ export type ExtensionList<ExtType extends ExtensionType = ExtensionType> = Record<string, ExtensionListData<ExtType>>;
82
76
 
83
77
  /**
84
78
  * Return value of {@linkcode ExtensionCliCommand._run}
@@ -171,7 +165,7 @@ class NotUpdatableError extends Error {}
171
165
 
172
166
  class NoUpdatesAvailableError extends Error {}
173
167
 
174
- abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType> {
168
+ export abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType> {
175
169
  /**
176
170
  * This is the `DriverConfig` or `PluginConfig`, depending on `ExtType`.
177
171
  */
@@ -264,13 +258,8 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
264
258
 
265
259
  /**
266
260
  * Build the initial list data structure from installed and known extensions
267
- *
268
261
  */
269
- protected async _install({
270
- installSpec,
271
- installType,
272
- packageName,
273
- }: InstallOpts): Promise<Record<string, any>> {
262
+ protected async _install({installSpec, installType, packageName}: InstallOpts): Promise<Record<string, any>> {
274
263
  if (packageName && [INSTALL_TYPE_LOCAL, INSTALL_TYPE_NPM].includes(installType)) {
275
264
  throw this._createFatalError(`When using --source=${installType}, cannot also use --package`);
276
265
  }
@@ -292,8 +281,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
292
281
  if (installType === INSTALL_TYPE_GITHUB) {
293
282
  if (installSpec.split('/').length !== 2) {
294
283
  throw this._createFatalError(
295
- `Github ${this.type} spec ${installSpec} appeared to be invalid; ` +
296
- 'it should be of the form <org>/<repo>',
284
+ `Github ${this.type} spec ${installSpec} appeared to be invalid; ` + 'it should be of the form <org>/<repo>',
297
285
  );
298
286
  }
299
287
  installViaNpmOpts = {
@@ -397,10 +385,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
397
385
  ]);
398
386
  const errorMap = new Map([[extName, errors]]);
399
387
  const warningMap = new Map([[extName, warnings]]);
400
- const {errorSummaries, warningSummaries} = this.config.getValidationResultSummaries(
401
- errorMap,
402
- warningMap,
403
- );
388
+ const {errorSummaries, warningSummaries} = this.config.getValidationResultSummaries(errorMap, warningMap);
404
389
 
405
390
  if (!util.isEmpty(errorSummaries)) {
406
391
  throw this._createFatalError(errorSummaries.join('\n'));
@@ -419,9 +404,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
419
404
  }
420
405
 
421
406
  // log info for the user
422
- this.log.info(
423
- this.getPostInstallText({extName, extData: receipt as unknown as ExtInstallReceipt<ExtType>}),
424
- );
407
+ this.log.info(this.getPostInstallText({extName, extData: receipt as unknown as ExtInstallReceipt<ExtType>}));
425
408
 
426
409
  return this.config.installedExtensions;
427
410
  }
@@ -437,9 +420,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
437
420
  */
438
421
  protected async _uninstall({installSpec}: UninstallOpts): Promise<Record<string, any>> {
439
422
  if (!this.config.isInstalled(installSpec)) {
440
- throw this._createFatalError(
441
- `Can't uninstall ${this.type} '${installSpec}'; it is not installed`,
442
- );
423
+ throw this._createFatalError(`Can't uninstall ${this.type} '${installSpec}'; it is not installed`);
443
424
  }
444
425
  const extRecord = this.config.installedExtensions[installSpec];
445
426
  if (extRecord.installType === INSTALL_TYPE_DEV) {
@@ -451,30 +432,20 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
451
432
  await npm.uninstallPackage(this.config.appiumHome, pkgName);
452
433
  });
453
434
  await this.config.removeExtension(installSpec);
454
- this.log.ok(
455
- console.styleText('green', `Successfully uninstalled ${this.type} '${installSpec}'`),
456
- );
435
+ this.log.ok(console.styleText('green', `Successfully uninstalled ${this.type} '${installSpec}'`));
457
436
  return this.config.installedExtensions;
458
437
  }
459
438
 
460
439
  /**
461
440
  * Attempt to update one or more drivers using NPM
462
- *
463
441
  */
464
- protected async _update({
465
- installSpec,
466
- unsafe,
467
- }: ExtensionUpdateOpts): Promise<ExtensionUpdateResult> {
442
+ protected async _update({installSpec, unsafe}: ExtensionUpdateOpts): Promise<ExtensionUpdateResult> {
468
443
  const shouldUpdateAll = installSpec === UPDATE_ALL;
469
444
  // if we're specifically requesting an update for an extension, make sure it's installed
470
445
  if (!shouldUpdateAll && !this.config.isInstalled(installSpec)) {
471
- throw this._createFatalError(
472
- `The ${this.type} "${installSpec}" was not installed, so can't be updated`,
473
- );
446
+ throw this._createFatalError(`The ${this.type} "${installSpec}" was not installed, so can't be updated`);
474
447
  }
475
- const extsToUpdate = shouldUpdateAll
476
- ? Object.keys(this.config.installedExtensions)
477
- : [installSpec];
448
+ const extsToUpdate = shouldUpdateAll ? Object.keys(this.config.installedExtensions) : [installSpec];
478
449
 
479
450
  // 'errors' will have ext names as keys and error objects as values
480
451
  const errors: Record<string, Error> = {};
@@ -534,18 +505,13 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
534
505
  this.log.info('Update report:');
535
506
 
536
507
  for (const [e, update] of Object.entries(updates)) {
537
- this.log.ok(
538
- console.styleText('green', ` - ${this.type} ${e} updated: ${update.from} => ${update.to}`),
539
- );
508
+ this.log.ok(console.styleText('green', ` - ${this.type} ${e} updated: ${update.from} => ${update.to}`));
540
509
  }
541
510
 
542
511
  for (const [e, err] of Object.entries(errors)) {
543
512
  if (err instanceof NotUpdatableError) {
544
513
  this.log.warn(
545
- console.styleText(
546
- 'yellow',
547
- ` - '${e}' was not installed via npm, so we could not check for updates`,
548
- ),
514
+ console.styleText('yellow', ` - '${e}' was not installed via npm, so we could not check for updates`),
549
515
  );
550
516
  } else if (err instanceof NoUpdatesAvailableError) {
551
517
  this.log.info(console.styleText('yellow', ` - '${e}' had no updates available`));
@@ -569,11 +535,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
569
535
  // install type
570
536
  const {version, pkgName} = this.config.installedExtensions[ext];
571
537
  let unsafeUpdate = await npm.getLatestVersion(this.config.appiumHome, pkgName);
572
- let safeUpdate = await npm.getLatestSafeUpgradeVersion(
573
- this.config.appiumHome,
574
- pkgName,
575
- version,
576
- );
538
+ let safeUpdate = await npm.getLatestSafeUpgradeVersion(this.config.appiumHome, pkgName, version);
577
539
  if (unsafeUpdate !== null && !util.compareVersions(unsafeUpdate, '>', version)) {
578
540
  // the latest version is not greater than the current version, so there's no possible update
579
541
  unsafeUpdate = null;
@@ -605,18 +567,14 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
605
567
  const moduleRoot = this.config.getInstallPath(installSpec);
606
568
  const packageJsonPath = path.join(moduleRoot, 'package.json');
607
569
  if (!(await fs.exists(packageJsonPath))) {
608
- throw this._createFatalError(
609
- `No package.json could be found for "${installSpec}" ${this.type}`,
610
- );
570
+ throw this._createFatalError(`No package.json could be found for "${installSpec}" ${this.type}`);
611
571
  }
612
572
  let doctorSpec: {checks: string[]} | undefined;
613
573
  try {
614
574
  doctorSpec = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')).appium?.doctor;
615
575
  } catch (e) {
616
576
  const message = e instanceof Error ? e.message : String(e);
617
- throw this._createFatalError(
618
- `The manifest at '${packageJsonPath}' cannot be parsed: ${message}`,
619
- );
577
+ throw this._createFatalError(`The manifest at '${packageJsonPath}' cannot be parsed: ${message}`);
620
578
  }
621
579
  if (!doctorSpec) {
622
580
  this.log.info(`The ${this.type} "${installSpec}" does not export any doctor checks`);
@@ -668,8 +626,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
668
626
  return 0;
669
627
  }
670
628
  this.log.debug(
671
- `Running ${util.pluralize('doctor check', checks.length, true)} ` +
672
- `for the "${installSpec}" ${this.type}`,
629
+ `Running ${util.pluralize('doctor check', checks.length, true)} ` + `for the "${installSpec}" ${this.type}`,
673
630
  );
674
631
  const exitCode = await new Doctor(checks).run();
675
632
  if (exitCode !== DOCTOR_EXIT_CODE.SUCCESS) {
@@ -685,7 +642,6 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
685
642
  * underneath the `appium` field in its `package.json`, if the
686
643
  * `scripts` field is not a plain object, or if the `scriptName` is
687
644
  * not found within `scripts` object.
688
- *
689
645
  */
690
646
  protected async _run({
691
647
  installSpec,
@@ -710,18 +666,13 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
710
666
  const extScripts = extConfig.scripts;
711
667
 
712
668
  if (!extScripts || !util.isPlainObject(extScripts)) {
713
- throw this._createFatalError(
714
- `The ${this.type} named '${installSpec}' "scripts" field must be a plain object`,
715
- );
669
+ throw this._createFatalError(`The ${this.type} named '${installSpec}' "scripts" field must be a plain object`);
716
670
  }
717
671
 
718
672
  if (!scriptName) {
719
673
  const allScripts = Object.entries(extScripts as Record<string, string>);
720
674
  const root = this.config.getInstallPath(installSpec);
721
- const existingScripts = await asyncfilter(
722
- allScripts,
723
- async ([, p]) => await fs.exists(path.join(root, p)),
724
- );
675
+ const existingScripts = await asyncfilter(allScripts, async ([, p]) => await fs.exists(path.join(root, p)));
725
676
  if (util.isEmpty(existingScripts)) {
726
677
  this.log.info(`The ${this.type} named '${installSpec}' does not contain any scripts`);
727
678
  } else {
@@ -745,9 +696,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
745
696
  const moduleRoot = this.config.getInstallPath(installSpec);
746
697
  const normalizedScriptPath = path.normalize(path.resolve(moduleRoot, scriptPath));
747
698
  if (!normalizedScriptPath.startsWith(path.normalize(moduleRoot))) {
748
- throw this._createFatalError(
749
- `The '${scriptPath}' script must be located in the '${moduleRoot}' folder`,
750
- );
699
+ throw this._createFatalError(`The '${scriptPath}' script must be located in the '${moduleRoot}' folder`);
751
700
  }
752
701
 
753
702
  if (bufferOutput) {
@@ -824,7 +773,6 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
824
773
 
825
774
  /**
826
775
  * Install an extension via NPM
827
- *
828
776
  */
829
777
  private async installViaNpm({
830
778
  installSpec,
@@ -837,8 +785,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
837
785
 
838
786
  // the string used for installation is either <name>@<ver> in the case of a standard NPM
839
787
  // package, or whatever the user sent in otherwise.
840
- const installStr =
841
- installType === INSTALL_TYPE_NPM ? `${pkgName}${pkgVer ? `@${pkgVer}` : ''}` : installSpec;
788
+ const installStr = installType === INSTALL_TYPE_NPM ? `${pkgName}${pkgVer ? `@${pkgVer}` : ''}` : installSpec;
842
789
  const appiumHome = this.config.appiumHome;
843
790
  try {
844
791
  const {pkg, installPath} = await spinWith(
@@ -900,12 +847,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
900
847
  * @param args - Extra args for script
901
848
  * @param opts - Options
902
849
  */
903
- private _runUnbuffered(
904
- cwd: string,
905
- script: string,
906
- args: string[] = [],
907
- opts: Record<string, any> = {},
908
- ) {
850
+ private _runUnbuffered(cwd: string, script: string, args: string[] = [], opts: Record<string, any> = {}) {
909
851
  return spawn(process.execPath, [script, ...args], {
910
852
  cwd,
911
853
  stdio: 'inherit',
@@ -915,7 +857,6 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
915
857
 
916
858
  /**
917
859
  * Once a package is installed on-disk, this gathers some necessary metadata for validation.
918
- *
919
860
  */
920
861
  private getInstallationReceipt({
921
862
  pkg,
@@ -958,9 +899,7 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
958
899
  const {appium, name, version} = pkg;
959
900
 
960
901
  const createMissingFieldError = (field: string): ReferenceError =>
961
- new ReferenceError(
962
- `${this.type} "${installSpec}" invalid; missing a \`${field}\` field of its \`package.json\``,
963
- );
902
+ new ReferenceError(`${this.type} "${installSpec}" invalid; missing a \`${field}\` field of its \`package.json\``);
964
903
 
965
904
  if (!name) {
966
905
  throw createMissingFieldError('name');
@@ -979,13 +918,8 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
979
918
 
980
919
  /**
981
920
  * Check for available updates for installed extensions
982
- *
983
921
  */
984
- private async _checkForUpdates(
985
- listData: ExtensionList,
986
- showUpdates: boolean,
987
- lsMsg: string,
988
- ): Promise<void> {
922
+ private async _checkForUpdates(listData: ExtensionList, showUpdates: boolean, lsMsg: string): Promise<void> {
989
923
  await spinWith(this.isJsonOutput, lsMsg, async () => {
990
924
  // We'd like to still show lsMsg even if showUpdates is false
991
925
  if (!showUpdates) {
@@ -1016,7 +950,6 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1016
950
 
1017
951
  /**
1018
952
  * Add repository URLs to list data for all extensions
1019
- *
1020
953
  */
1021
954
  private async _addRepositoryUrlsToListData(listData: ExtensionList): Promise<void> {
1022
955
  await spinWith(this.isJsonOutput, 'Fetching repository information', async () => {
@@ -1035,12 +968,8 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1035
968
 
1036
969
  /**
1037
970
  * Display normal formatted output
1038
- *
1039
971
  */
1040
- private async _displayNormalListOutput(
1041
- listData: ExtensionList,
1042
- showUpdates: boolean,
1043
- ): Promise<ExtensionList> {
972
+ private async _displayNormalListOutput(listData: ExtensionList, showUpdates: boolean): Promise<ExtensionList> {
1044
973
  for (const [name, data] of Object.entries(listData)) {
1045
974
  const line = await this._formatExtensionLine(name, data, showUpdates);
1046
975
  this.log.log(line);
@@ -1051,13 +980,8 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1051
980
 
1052
981
  /**
1053
982
  * Format a single extension line for display
1054
- *
1055
983
  */
1056
- private async _formatExtensionLine(
1057
- name: string,
1058
- data: ExtensionListData,
1059
- showUpdates: boolean,
1060
- ): Promise<string> {
984
+ private async _formatExtensionLine(name: string, data: ExtensionListData, showUpdates: boolean): Promise<string> {
1061
985
  if (data.installed) {
1062
986
  const installTxt = this._formatInstallText(data);
1063
987
  const updateTxt = showUpdates ? this._formatUpdateText(data) : '';
@@ -1069,7 +993,6 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1069
993
 
1070
994
  /**
1071
995
  * Format installation status text
1072
- *
1073
996
  */
1074
997
  private _formatInstallText(data: ExtensionListData): string {
1075
998
  const {installType, installSpec, version} = data;
@@ -1094,12 +1017,14 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1094
1017
  const installLabelStart = console.styleText('green', '[installed ');
1095
1018
  const installLabelEnd = console.styleText('green', ']');
1096
1019
  const installTypeText = isTypeTextStyled ? typeTxt : console.styleText('green', typeTxt);
1097
- return `${console.styleText('yellow', `@${String(version)}`)} ${installLabelStart}${installTypeText}${installLabelEnd}`;
1020
+ return `${console.styleText(
1021
+ 'yellow',
1022
+ `@${String(version)}`,
1023
+ )} ${installLabelStart}${installTypeText}${installLabelEnd}`;
1098
1024
  }
1099
1025
 
1100
1026
  /**
1101
1027
  * Format update information text
1102
- *
1103
1028
  */
1104
1029
  private _formatUpdateText(data: ExtensionListData): string {
1105
1030
  const {updateVersion, unsafeUpdateVersion, upToDate, updateError} = data;
@@ -1121,7 +1046,6 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1121
1046
 
1122
1047
  /**
1123
1048
  * Get repository URL from package data
1124
- *
1125
1049
  */
1126
1050
  private async _getRepositoryUrl(data: ExtensionListData): Promise<string | null> {
1127
1051
  if (data.installed && data.installPath) {
@@ -1135,7 +1059,6 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1135
1059
 
1136
1060
  /**
1137
1061
  * Get repository URL from installed extension's package.json
1138
- *
1139
1062
  */
1140
1063
  private async _getRepositoryUrlFromInstalled(data: ExtensionListData): Promise<string | null> {
1141
1064
  try {
@@ -1159,7 +1082,6 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1159
1082
 
1160
1083
  /**
1161
1084
  * Get repository URL from npm for a package name
1162
- *
1163
1085
  */
1164
1086
  private async _getRepositoryUrlFromNpm(pkgName: string): Promise<string | null> {
1165
1087
  try {
@@ -1181,7 +1103,6 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1181
1103
 
1182
1104
  /**
1183
1105
  * Checks whether the given extension is compatible with the currently installed server
1184
- *
1185
1106
  */
1186
1107
  private async _checkInstallCompatibility({
1187
1108
  installSpec,
@@ -1194,15 +1115,8 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1194
1115
  }
1195
1116
 
1196
1117
  await spinWith(this.isJsonOutput, `Checking if '${pkgName}' is compatible`, async () => {
1197
- const [serverVersion, extVersionRequirement] = await getRemoteExtensionVersionReq(
1198
- pkgName,
1199
- pkgVer,
1200
- );
1201
- if (
1202
- serverVersion &&
1203
- extVersionRequirement &&
1204
- !semver.satisfies(serverVersion, extVersionRequirement)
1205
- ) {
1118
+ const [serverVersion, extVersionRequirement] = await getRemoteExtensionVersionReq(pkgName, pkgVer);
1119
+ if (serverVersion && extVersionRequirement && !semver.satisfies(serverVersion, extVersionRequirement)) {
1206
1120
  throw this._createFatalError(
1207
1121
  `'${installSpec}' cannot be installed because the server version it requires (${extVersionRequirement}) ` +
1208
1122
  `does not meet the currently installed one (${serverVersion}). Please install ` +
@@ -1220,15 +1134,11 @@ abstract class ExtensionCliCommand<ExtType extends ExtensionType = ExtensionType
1220
1134
  * @param extMetadata - the data in the "appium" field of `package.json` for an extension
1221
1135
  * @param installSpec - Extension name/spec
1222
1136
  */
1223
- protected abstract validateExtensionFields(
1224
- extMetadata: ExtMetadata<ExtType>,
1225
- installSpec: string,
1226
- ): void;
1137
+ protected abstract validateExtensionFields(extMetadata: ExtMetadata<ExtType>, installSpec: string): void;
1227
1138
 
1228
1139
  /**
1229
1140
  * Get the text which should be displayed to the user after an extension has been installed. This
1230
1141
  * is designed to be overridden by drivers/plugins with their own particular text.
1231
- *
1232
1142
  */
1233
1143
  protected abstract getPostInstallText(args: ExtensionArgs<ExtType>): PostInstallText;
1234
1144
  }
@@ -1271,18 +1181,14 @@ export async function injectAppiumSymlinks(
1271
1181
  // as these might be cleaned up unexpectedly by npm
1272
1182
  // (see https://github.com/appium/python-client/pull/1177#issuecomment-3419826643).
1273
1183
  await Promise.all(
1274
- installPaths.map((installPath) =>
1275
- injectAppiumSymlink(path.join(installPath, 'node_modules'), logger),
1276
- ),
1184
+ installPaths.map((installPath) => injectAppiumSymlink(path.join(installPath, 'node_modules'), logger)),
1277
1185
  );
1278
1186
  }
1279
1187
 
1280
1188
  /**
1281
1189
  * Omits `driverName`/`pluginName` props from the receipt to make a {@linkcode ExtManifest}
1282
1190
  */
1283
- function receiptToManifest<ExtType extends ExtensionType>(
1284
- receipt: ExtInstallReceipt<ExtType>,
1285
- ): ExtManifest<ExtType> {
1191
+ function receiptToManifest<ExtType extends ExtensionType>(receipt: ExtInstallReceipt<ExtType>): ExtManifest<ExtType> {
1286
1192
  if ('driverName' in receipt) {
1287
1193
  const {driverName, ...manifest} = receipt as ExtInstallReceipt<'driver'>;
1288
1194
  void driverName;
@@ -1299,10 +1205,7 @@ function receiptToManifest<ExtType extends ExtensionType>(
1299
1205
  * @param pkgName Extension name
1300
1206
  * @param [pkgVer] Extension version (if not provided then the latest is assumed)
1301
1207
  */
1302
- async function getRemoteExtensionVersionReq(
1303
- pkgName: string,
1304
- pkgVer?: string,
1305
- ): Promise<[string, string | null]> {
1208
+ async function getRemoteExtensionVersionReq(pkgName: string, pkgVer?: string): Promise<[string, string | null]> {
1306
1209
  const allDeps = await npm.getPackageInfo(`${pkgName}${pkgVer ? `@${pkgVer}` : ``}`, [
1307
1210
  'peerDependencies',
1308
1211
  'dependencies',
@@ -1310,10 +1213,7 @@ async function getRemoteExtensionVersionReq(
1310
1213
  const requiredVersionPair = Object.values(allDeps)
1311
1214
  .flatMap((dep) => Object.entries(dep ?? {}))
1312
1215
  .find(([name]) => name === 'appium');
1313
- return [
1314
- npmPackage.version,
1315
- requiredVersionPair ? (requiredVersionPair[1] as string | null) : null,
1316
- ];
1216
+ return [npmPackage.version, requiredVersionPair ? (requiredVersionPair[1] as string | null) : null];
1317
1217
  }
1318
1218
 
1319
1219
  /**
@@ -1338,4 +1238,3 @@ async function injectAppiumSymlink(dstFolder: string, logger: AppiumLogger): Pro
1338
1238
  }
1339
1239
 
1340
1240
  export default ExtensionCliCommand;
1341
- export {ExtensionCliCommand as ExtensionCommand};
@@ -1,8 +1,9 @@
1
1
  /* eslint-disable no-console */
2
2
  import type {Class, DriverType, ExtensionType, PluginType} from '@appium/types';
3
3
  import type {Args, CliExtensionCommand, CliExtensionSubcommand} from 'appium/types';
4
- import type {ExtensionConfig} from '../extension/extension-config';
4
+
5
5
  import {DRIVER_TYPE, PLUGIN_TYPE} from '../constants';
6
+ import type {ExtensionConfig} from '../extension/extension-config';
6
7
  import {isExtensionCommandArgs} from '../schema/cli-args-guards';
7
8
  import DriverCliCommand from './driver-command';
8
9
  import PluginCliCommand from './plugin-command';
@@ -25,10 +26,10 @@ export type ExtCommand<ExtType extends ExtensionType> = ExtType extends DriverTy
25
26
  * When JSON output is enabled, this also prints the serialized command result
26
27
  * unless output was suppressed by the caller.
27
28
  */
28
- export async function runExtensionCommand<
29
- Cmd extends CliExtensionCommand,
30
- SubCmd extends CliExtensionSubcommand,
31
- >(args: Args<Cmd, SubCmd>, config: ExtensionConfig<Cmd>) {
29
+ export async function runExtensionCommand<Cmd extends CliExtensionCommand, SubCmd extends CliExtensionSubcommand>(
30
+ args: Args<Cmd, SubCmd>,
31
+ config: ExtensionConfig<Cmd>,
32
+ ) {
32
33
  // TODO driver config file should be locked while any of these commands are
33
34
  // running to prevent weird situations
34
35
  let jsonResult: Record<string, unknown> = {};
package/lib/cli/parser.ts CHANGED
@@ -1,9 +1,10 @@
1
- import {ArgumentParser} from 'argparse';
2
- import type {SubArgumentParserOptions, SubParser} from 'argparse';
3
1
  import path from 'node:path';
4
- import {setPath} from '../utils';
2
+
5
3
  import type {DriverType, PluginType} from '@appium/types';
6
4
  import type {CliExtensionSubcommand} from 'appium/types';
5
+ import {ArgumentParser} from 'argparse';
6
+ import type {SubArgumentParserOptions, SubparsersAction} from 'argparse';
7
+
7
8
  import {
8
9
  DRIVER_TYPE,
9
10
  EXT_SUBCOMMAND_DOCTOR,
@@ -16,18 +17,19 @@ import {
16
17
  SERVER_SUBCOMMAND,
17
18
  SETUP_SUBCOMMAND,
18
19
  } from '../constants';
19
- import {finalizeSchema, getAllArgSpecs, getArgSpec, hasArgSpec} from '../schema';
20
20
  import {APPIUM_VER} from '../helpers/build';
21
+ import {finalizeSchema, getAllArgSpecs, getArgSpec, hasArgSpec} from '../schema';
22
+ import {setPath} from '../utils';
21
23
  import {getExtensionArgs, getServerArgs} from './args';
22
24
  import type {ArgumentDefinitions} from './args';
23
25
  import {
24
26
  DEFAULT_PLUGINS,
25
- SUBCOMMAND_MOBILE,
26
- SUBCOMMAND_DESKTOP,
27
+ determinePlatformName,
28
+ getPresetDrivers,
27
29
  SUBCOMMAND_BROWSER,
30
+ SUBCOMMAND_DESKTOP,
31
+ SUBCOMMAND_MOBILE,
28
32
  SUBCOMMAND_RESET,
29
- getPresetDrivers,
30
- determinePlatformName,
31
33
  } from './setup-command';
32
34
 
33
35
  export const EXTRA_ARGS = 'extraArgs';
@@ -37,16 +39,7 @@ export const EXTRA_ARGS = 'extraArgs';
37
39
  * will automatically inject the `server` subcommand.
38
40
  */
39
41
  const NON_SERVER_ARGS = Object.freeze(
40
- new Set([
41
- SETUP_SUBCOMMAND,
42
- DRIVER_TYPE,
43
- PLUGIN_TYPE,
44
- SERVER_SUBCOMMAND,
45
- '-h',
46
- '--help',
47
- '-v',
48
- '--version',
49
- ]),
42
+ new Set([SETUP_SUBCOMMAND, DRIVER_TYPE, PLUGIN_TYPE, SERVER_SUBCOMMAND, '-h', '--help', '-v', '--version']),
50
43
  );
51
44
 
52
45
  type LooseArgsMap = {[key: string]: any};
@@ -134,10 +127,7 @@ export class ArgParser {
134
127
  *
135
128
  * E.g., `{'driver-foo-bar': baz}` becomes `{driver: {foo: {bar: 'baz'}}}`
136
129
  */
137
- private static _transformParsedArgs(
138
- args: LooseArgsMap,
139
- unknownArgs: string[] = [],
140
- ): TransformedArgsMap {
130
+ private static _transformParsedArgs(args: LooseArgsMap, unknownArgs: string[] = []): TransformedArgsMap {
141
131
  const result = Object.entries(args).reduce((unpacked: LooseArgsMap, [key, value]) => {
142
132
  const spec = hasArgSpec(key) ? getArgSpec(key) : undefined;
143
133
  if (value !== undefined && spec) {
@@ -168,7 +158,7 @@ export class ArgParser {
168
158
  /**
169
159
  * Adds the `server` subcommand parser and returns its argument definitions.
170
160
  */
171
- private static _addServerToParser(subParser: SubParser): ArgumentDefinitions {
161
+ private static _addServerToParser(subParser: SubparsersAction): ArgumentDefinitions {
172
162
  const serverParser = subParser.add_parser('server', {
173
163
  add_help: true,
174
164
  help: 'Start an Appium server',
@@ -189,7 +179,7 @@ export class ArgParser {
189
179
  /**
190
180
  * Adds extension sub-sub-commands to `driver`/`plugin` subcommands
191
181
  */
192
- private static _addExtensionCommandsToParser(subParser: SubParser): void {
182
+ private static _addExtensionCommandsToParser(subParser: SubparsersAction): void {
193
183
  for (const type of [DRIVER_TYPE, PLUGIN_TYPE] as [DriverType, PluginType]) {
194
184
  const extParser = subParser.add_parser(type, {
195
185
  add_help: true,
@@ -262,7 +252,7 @@ export class ArgParser {
262
252
  /**
263
253
  * Add subcommand and sub-sub commands for 'setup' subcommand.
264
254
  */
265
- private static _addSetupToParser(subParser: SubParser): void {
255
+ private static _addSetupToParser(subParser: SubparsersAction): void {
266
256
  const setupParser = subParser.add_parser('setup', {
267
257
  add_help: true,
268
258
  help: 'Batch install or uninstall Appium drivers and plugins',
@@ -330,12 +320,16 @@ export class ArgParser {
330
320
  } else if (knownArgs?.pluginCommand === 'ls') {
331
321
  knownArgs.pluginCommand = 'list';
332
322
  }
333
- if (
334
- unknownArgs?.length &&
335
- (knownArgs.driverCommand === 'run' || knownArgs.pluginCommand === 'run')
336
- ) {
323
+ if (unknownArgs?.length && (knownArgs.driverCommand === 'run' || knownArgs.pluginCommand === 'run')) {
337
324
  return ArgParser._transformParsedArgs(knownArgs, unknownArgs);
338
325
  } else if (unknownArgs?.length) {
326
+ if (knownArgs.allowUnknownArgs) {
327
+ // eslint-disable-next-line no-console
328
+ console.error(
329
+ `[WARN] Ignoring unrecognized arguments because '--allow-unknown-args' is set: ${unknownArgs.join(' ')}`,
330
+ );
331
+ return ArgParser._transformParsedArgs(knownArgs);
332
+ }
339
333
  throw new Error(`[ERROR] Unrecognized arguments: ${unknownArgs.join(' ')}`);
340
334
  }
341
335
  return ArgParser._transformParsedArgs(knownArgs);