appium 3.5.2 → 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.
- package/build/lib/appium.d.ts +3 -4
- package/build/lib/appium.d.ts.map +1 -1
- package/build/lib/appium.js +10 -19
- package/build/lib/appium.js.map +1 -1
- package/build/lib/bidi-commands.d.ts +2 -2
- package/build/lib/bidi-commands.d.ts.map +1 -1
- package/build/lib/bidi-commands.js +4 -4
- package/build/lib/bidi-commands.js.map +1 -1
- package/build/lib/bootstrap/appium-initializer.d.ts.map +1 -1
- package/build/lib/bootstrap/appium-initializer.js +12 -16
- package/build/lib/bootstrap/appium-initializer.js.map +1 -1
- package/build/lib/bootstrap/appium-main-runner.d.ts +1 -1
- package/build/lib/bootstrap/appium-main-runner.d.ts.map +1 -1
- package/build/lib/bootstrap/appium-main-runner.js +2 -2
- package/build/lib/bootstrap/appium-main-runner.js.map +1 -1
- package/build/lib/bootstrap/config-file.d.ts +1 -1
- package/build/lib/bootstrap/config-file.d.ts.map +1 -1
- package/build/lib/bootstrap/config-file.js +13 -15
- package/build/lib/bootstrap/config-file.js.map +1 -1
- package/build/lib/bootstrap/grid-v3-register.d.ts.map +1 -1
- package/build/lib/bootstrap/grid-v3-register.js +7 -14
- package/build/lib/bootstrap/grid-v3-register.js.map +1 -1
- package/build/lib/bootstrap/init-types.d.ts +1 -1
- package/build/lib/bootstrap/init-types.d.ts.map +1 -1
- package/build/lib/bootstrap/main-helpers.d.ts +1 -1
- package/build/lib/bootstrap/main-helpers.d.ts.map +1 -1
- package/build/lib/bootstrap/main-helpers.js +5 -6
- package/build/lib/bootstrap/main-helpers.js.map +1 -1
- package/build/lib/bootstrap/node-helpers.d.ts +1 -1
- package/build/lib/bootstrap/node-helpers.d.ts.map +1 -1
- package/build/lib/bootstrap/node-helpers.js +6 -8
- package/build/lib/bootstrap/node-helpers.js.map +1 -1
- package/build/lib/bootstrap/startup-config.d.ts.map +1 -1
- package/build/lib/bootstrap/startup-config.js.map +1 -1
- package/build/lib/cli/args.d.ts +2 -4
- package/build/lib/cli/args.d.ts.map +1 -1
- package/build/lib/cli/args.js +3 -6
- package/build/lib/cli/args.js.map +1 -1
- package/build/lib/cli/driver-command.d.ts +2 -2
- package/build/lib/cli/driver-command.d.ts.map +1 -1
- package/build/lib/cli/driver-command.js +4 -7
- package/build/lib/cli/driver-command.js.map +1 -1
- package/build/lib/cli/extension-command.d.ts +3 -20
- package/build/lib/cli/extension-command.d.ts.map +1 -1
- package/build/lib/cli/extension-command.js +32 -56
- package/build/lib/cli/extension-command.js.map +1 -1
- package/build/lib/cli/extension.d.ts.map +1 -1
- package/build/lib/cli/extension.js.map +1 -1
- package/build/lib/cli/parser.d.ts.map +1 -1
- package/build/lib/cli/parser.js +10 -15
- package/build/lib/cli/parser.js.map +1 -1
- package/build/lib/cli/plugin-command.d.ts +2 -2
- package/build/lib/cli/plugin-command.d.ts.map +1 -1
- package/build/lib/cli/plugin-command.js +4 -7
- package/build/lib/cli/plugin-command.js.map +1 -1
- package/build/lib/cli/setup-command.d.ts.map +1 -1
- package/build/lib/cli/setup-command.js +2 -2
- package/build/lib/cli/setup-command.js.map +1 -1
- package/build/lib/cli/utils.d.ts.map +1 -1
- package/build/lib/cli/utils.js.map +1 -1
- package/build/lib/doctor/doctor.d.ts.map +1 -1
- package/build/lib/doctor/doctor.js +1 -4
- package/build/lib/doctor/doctor.js.map +1 -1
- package/build/lib/extension/driver-config.d.ts +1 -1
- package/build/lib/extension/driver-config.d.ts.map +1 -1
- package/build/lib/extension/driver-config.js +2 -4
- package/build/lib/extension/driver-config.js.map +1 -1
- package/build/lib/extension/extension-config.d.ts +1 -1
- package/build/lib/extension/extension-config.d.ts.map +1 -1
- package/build/lib/extension/extension-config.js +10 -10
- package/build/lib/extension/extension-config.js.map +1 -1
- package/build/lib/extension/index.d.ts.map +1 -1
- package/build/lib/extension/index.js +3 -5
- package/build/lib/extension/index.js.map +1 -1
- package/build/lib/extension/manifest-migrations.d.ts.map +1 -1
- package/build/lib/extension/manifest-migrations.js.map +1 -1
- package/build/lib/extension/manifest.d.ts.map +1 -1
- package/build/lib/extension/manifest.js +2 -2
- package/build/lib/extension/manifest.js.map +1 -1
- package/build/lib/extension/plugin-config.d.ts.map +1 -1
- package/build/lib/extension/plugin-config.js +1 -2
- package/build/lib/extension/plugin-config.js.map +1 -1
- package/build/lib/helpers/build.d.ts.map +1 -1
- package/build/lib/helpers/build.js +1 -1
- package/build/lib/helpers/build.js.map +1 -1
- package/build/lib/helpers/capability.d.ts.map +1 -1
- package/build/lib/helpers/capability.js +2 -4
- package/build/lib/helpers/capability.js.map +1 -1
- package/build/lib/helpers/network.d.ts.map +1 -1
- package/build/lib/helpers/network.js +1 -3
- package/build/lib/helpers/network.js.map +1 -1
- package/build/lib/insecure-features.d.ts +1 -1
- package/build/lib/insecure-features.d.ts.map +1 -1
- package/build/lib/insecure-features.js +2 -6
- package/build/lib/insecure-features.js.map +1 -1
- package/build/lib/inspector-commands.d.ts.map +1 -1
- package/build/lib/inspector-commands.js +6 -16
- package/build/lib/inspector-commands.js.map +1 -1
- package/build/lib/logsink.d.ts.map +1 -1
- package/build/lib/logsink.js +5 -9
- package/build/lib/logsink.js.map +1 -1
- package/build/lib/main.d.ts.map +1 -1
- package/build/lib/main.js.map +1 -1
- package/build/lib/schema/arg-spec.d.ts.map +1 -1
- package/build/lib/schema/arg-spec.js.map +1 -1
- package/build/lib/schema/cli-args-guards.d.ts +1 -1
- package/build/lib/schema/cli-args-guards.d.ts.map +1 -1
- package/build/lib/schema/cli-args-guards.js.map +1 -1
- package/build/lib/schema/cli-args.d.ts.map +1 -1
- package/build/lib/schema/cli-args.js +2 -2
- package/build/lib/schema/cli-args.js.map +1 -1
- package/build/lib/schema/cli-transformers.d.ts.map +1 -1
- package/build/lib/schema/cli-transformers.js +2 -4
- package/build/lib/schema/cli-transformers.js.map +1 -1
- package/build/lib/schema/format-errors.d.ts +1 -1
- package/build/lib/schema/format-errors.d.ts.map +1 -1
- package/build/lib/schema/format-errors.js.map +1 -1
- package/build/lib/schema/index.d.ts +2 -2
- package/build/lib/schema/index.d.ts.map +1 -1
- package/build/lib/schema/index.js +2 -2
- package/build/lib/schema/index.js.map +1 -1
- package/build/lib/schema/keywords.d.ts.map +1 -1
- package/build/lib/schema/keywords.js.map +1 -1
- package/build/lib/schema/schema.d.ts +1 -1
- package/build/lib/schema/schema.d.ts.map +1 -1
- package/build/lib/schema/schema.js +5 -7
- package/build/lib/schema/schema.js.map +1 -1
- package/build/lib/utils/index.d.ts +2 -2
- package/build/lib/utils/index.d.ts.map +1 -1
- package/build/lib/utils/index.js +8 -8
- package/build/lib/utils/index.js.map +1 -1
- package/build/lib/utils/is-package-changed.d.ts.map +1 -1
- package/build/lib/utils/is-package-changed.js +2 -4
- package/build/lib/utils/is-package-changed.js.map +1 -1
- package/build/lib/utils/object.d.ts.map +1 -1
- package/build/lib/utils/object.js +1 -3
- package/build/lib/utils/object.js.map +1 -1
- package/build/lib/utils/package-changed.d.ts +0 -1
- package/build/lib/utils/package-changed.d.ts.map +1 -1
- package/build/lib/utils/package-changed.js +4 -3
- package/build/lib/utils/package-changed.js.map +1 -1
- package/build/lib/utils/package-json.d.ts.map +1 -1
- package/build/lib/utils/package-json.js.map +1 -1
- package/build/lib/utils/resolve-from.d.ts.map +1 -1
- package/build/lib/utils/resolve-from.js.map +1 -1
- package/build/types/cli.d.ts.map +1 -1
- package/build/types/index.d.ts +2 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js +1 -1
- package/build/types/index.js.map +1 -1
- package/build/types/manifest/base.d.ts.map +1 -1
- package/build/types/manifest/v3.d.ts.map +1 -1
- package/build/types/manifest/v4.d.ts.map +1 -1
- package/lib/appium.ts +46 -94
- package/lib/bidi-commands.ts +28 -63
- package/lib/bootstrap/appium-initializer.ts +26 -38
- package/lib/bootstrap/appium-main-runner.ts +14 -32
- package/lib/bootstrap/config-file.ts +19 -37
- package/lib/bootstrap/grid-v3-register.ts +12 -38
- package/lib/bootstrap/init-types.ts +3 -5
- package/lib/bootstrap/main-helpers.ts +15 -25
- package/lib/bootstrap/node-helpers.ts +11 -22
- package/lib/bootstrap/startup-config.ts +13 -18
- package/lib/cli/args.ts +9 -18
- package/lib/cli/driver-command.ts +6 -13
- package/lib/cli/extension-command.ts +55 -156
- package/lib/cli/extension.ts +6 -5
- package/lib/cli/parser.ts +23 -29
- package/lib/cli/plugin-command.ts +7 -17
- package/lib/cli/setup-command.ts +10 -28
- package/lib/cli/utils.ts +1 -5
- package/lib/doctor/doctor.ts +1 -4
- package/lib/extension/driver-config.ts +5 -15
- package/lib/extension/extension-config.ts +36 -80
- package/lib/extension/index.ts +16 -31
- package/lib/extension/manifest-migrations.ts +1 -0
- package/lib/extension/manifest.ts +9 -19
- package/lib/extension/plugin-config.ts +5 -12
- package/lib/helpers/build.ts +4 -6
- package/lib/helpers/capability.ts +6 -17
- package/lib/helpers/network.ts +2 -6
- package/lib/insecure-features.ts +7 -22
- package/lib/inspector-commands.ts +28 -68
- package/lib/logsink.ts +11 -25
- package/lib/main.ts +2 -7
- package/lib/schema/arg-spec.ts +1 -0
- package/lib/schema/cli-args-guards.ts +7 -14
- package/lib/schema/cli-args.ts +10 -17
- package/lib/schema/cli-transformers.ts +5 -10
- package/lib/schema/format-errors.ts +2 -1
- package/lib/schema/index.ts +2 -2
- package/lib/schema/keywords.ts +2 -2
- package/lib/schema/schema.ts +14 -33
- package/lib/utils/index.ts +3 -3
- package/lib/utils/is-package-changed.ts +4 -7
- package/lib/utils/object.ts +4 -13
- package/lib/utils/package-changed.ts +7 -9
- package/lib/utils/package-json.ts +2 -3
- package/lib/utils/resolve-from.ts +1 -4
- package/package.json +32 -31
- package/scripts/autoinstall-extensions.js +1 -4
- package/tsconfig.json +7 -11
- package/types/cli.ts +2 -3
- package/types/index.ts +2 -2
- package/types/manifest/base.ts +3 -10
- package/types/manifest/v3.ts +3 -10
- package/types/manifest/v4.ts +3 -10
- package/LICENSE +0 -201
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
24
|
+
INSTALL_TYPE_DEV,
|
|
18
25
|
INSTALL_TYPE_GIT,
|
|
19
26
|
INSTALL_TYPE_GITHUB,
|
|
20
27
|
INSTALL_TYPE_LOCAL,
|
|
21
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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};
|
package/lib/cli/extension.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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);
|