appium 3.2.2 → 3.3.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.
- package/build/lib/appium.d.ts +147 -205
- package/build/lib/appium.d.ts.map +1 -1
- package/build/lib/appium.js +169 -282
- package/build/lib/appium.js.map +1 -1
- package/build/lib/bidi-commands.d.ts.map +1 -1
- package/build/lib/bidi-commands.js +11 -11
- package/build/lib/bidi-commands.js.map +1 -1
- package/build/lib/bootstrap/appium-initializer.d.ts +21 -0
- package/build/lib/bootstrap/appium-initializer.d.ts.map +1 -0
- package/build/lib/bootstrap/appium-initializer.js +146 -0
- package/build/lib/bootstrap/appium-initializer.js.map +1 -0
- package/build/lib/bootstrap/appium-main-runner.d.ts +22 -0
- package/build/lib/bootstrap/appium-main-runner.d.ts.map +1 -0
- package/build/lib/bootstrap/appium-main-runner.js +109 -0
- package/build/lib/bootstrap/appium-main-runner.js.map +1 -0
- package/build/lib/bootstrap/config-file.d.ts +37 -0
- package/build/lib/bootstrap/config-file.d.ts.map +1 -0
- package/build/lib/{config-file.js → bootstrap/config-file.js} +62 -138
- package/build/lib/bootstrap/config-file.js.map +1 -0
- package/build/lib/bootstrap/grid-v3-register.d.ts +20 -0
- package/build/lib/bootstrap/grid-v3-register.d.ts.map +1 -0
- package/build/lib/bootstrap/grid-v3-register.js +185 -0
- package/build/lib/bootstrap/grid-v3-register.js.map +1 -0
- package/build/lib/bootstrap/init-types.d.ts +16 -0
- package/build/lib/bootstrap/init-types.d.ts.map +1 -0
- package/build/lib/bootstrap/init-types.js +3 -0
- package/build/lib/bootstrap/init-types.js.map +1 -0
- package/build/lib/bootstrap/main-helpers.d.ts +55 -0
- package/build/lib/bootstrap/main-helpers.d.ts.map +1 -0
- package/build/lib/bootstrap/main-helpers.js +187 -0
- package/build/lib/bootstrap/main-helpers.js.map +1 -0
- package/build/lib/bootstrap/node-helpers.d.ts +32 -0
- package/build/lib/bootstrap/node-helpers.d.ts.map +1 -0
- package/build/lib/bootstrap/node-helpers.js +201 -0
- package/build/lib/bootstrap/node-helpers.js.map +1 -0
- package/build/lib/bootstrap/startup-config.d.ts +22 -0
- package/build/lib/bootstrap/startup-config.d.ts.map +1 -0
- package/build/lib/bootstrap/startup-config.js +111 -0
- package/build/lib/bootstrap/startup-config.js.map +1 -0
- package/build/lib/cli/args.d.ts +16 -12
- package/build/lib/cli/args.d.ts.map +1 -1
- package/build/lib/cli/args.js +20 -40
- package/build/lib/cli/args.js.map +1 -1
- package/build/lib/cli/driver-command.d.ts +51 -93
- package/build/lib/cli/driver-command.d.ts.map +1 -1
- package/build/lib/cli/driver-command.js +11 -66
- package/build/lib/cli/driver-command.js.map +1 -1
- package/build/lib/cli/extension-command.d.ts +173 -377
- package/build/lib/cli/extension-command.d.ts.map +1 -1
- package/build/lib/cli/extension-command.js +387 -656
- package/build/lib/cli/extension-command.js.map +1 -1
- package/build/lib/cli/extension.d.ts +10 -15
- package/build/lib/cli/extension.d.ts.map +1 -1
- package/build/lib/cli/extension.js +15 -33
- package/build/lib/cli/extension.js.map +1 -1
- package/build/lib/cli/parser.d.ts +37 -66
- package/build/lib/cli/parser.d.ts.map +1 -1
- package/build/lib/cli/parser.js +69 -104
- package/build/lib/cli/parser.js.map +1 -1
- package/build/lib/cli/plugin-command.d.ts +50 -90
- package/build/lib/cli/plugin-command.d.ts.map +1 -1
- package/build/lib/cli/plugin-command.js +11 -63
- package/build/lib/cli/plugin-command.js.map +1 -1
- package/build/lib/cli/setup-command.d.ts +21 -26
- package/build/lib/cli/setup-command.d.ts.map +1 -1
- package/build/lib/cli/setup-command.js +19 -61
- package/build/lib/cli/setup-command.js.map +1 -1
- package/build/lib/cli/utils.d.ts +33 -35
- package/build/lib/cli/utils.d.ts.map +1 -1
- package/build/lib/cli/utils.js +48 -50
- package/build/lib/cli/utils.js.map +1 -1
- package/build/lib/constants.d.ts +23 -23
- package/build/lib/constants.d.ts.map +1 -1
- package/build/lib/constants.js +10 -15
- package/build/lib/constants.js.map +1 -1
- package/build/lib/doctor/doctor.d.ts +40 -57
- package/build/lib/doctor/doctor.d.ts.map +1 -1
- package/build/lib/doctor/doctor.js +31 -62
- package/build/lib/doctor/doctor.js.map +1 -1
- package/build/lib/extension/driver-config.d.ts +18 -77
- package/build/lib/extension/driver-config.d.ts.map +1 -1
- package/build/lib/extension/driver-config.js +37 -125
- package/build/lib/extension/driver-config.js.map +1 -1
- package/build/lib/extension/extension-config.d.ts +103 -210
- package/build/lib/extension/extension-config.d.ts.map +1 -1
- package/build/lib/extension/extension-config.js +180 -342
- package/build/lib/extension/extension-config.js.map +1 -1
- package/build/lib/extension/index.d.ts +12 -29
- package/build/lib/extension/index.d.ts.map +1 -1
- package/build/lib/extension/index.js +33 -75
- package/build/lib/extension/index.js.map +1 -1
- package/build/lib/extension/manifest-migrations.d.ts +3 -20
- package/build/lib/extension/manifest-migrations.d.ts.map +1 -1
- package/build/lib/extension/manifest-migrations.js +20 -101
- package/build/lib/extension/manifest-migrations.js.map +1 -1
- package/build/lib/extension/manifest.d.ts +61 -107
- package/build/lib/extension/manifest.d.ts.map +1 -1
- package/build/lib/extension/manifest.js +181 -356
- package/build/lib/extension/manifest.js.map +1 -1
- package/build/lib/extension/package-changed.d.ts +1 -3
- package/build/lib/extension/package-changed.d.ts.map +1 -1
- package/build/lib/extension/package-changed.js +8 -15
- package/build/lib/extension/package-changed.js.map +1 -1
- package/build/lib/extension/plugin-config.d.ts +10 -52
- package/build/lib/extension/plugin-config.d.ts.map +1 -1
- package/build/lib/extension/plugin-config.js +11 -63
- package/build/lib/extension/plugin-config.js.map +1 -1
- package/build/lib/helpers/build.d.ts +22 -0
- package/build/lib/helpers/build.d.ts.map +1 -0
- package/build/lib/helpers/build.js +109 -0
- package/build/lib/helpers/build.js.map +1 -0
- package/build/lib/helpers/capability.d.ts +38 -0
- package/build/lib/helpers/capability.d.ts.map +1 -0
- package/build/lib/helpers/capability.js +128 -0
- package/build/lib/helpers/capability.js.map +1 -0
- package/build/lib/helpers/network.d.ts +14 -0
- package/build/lib/helpers/network.d.ts.map +1 -0
- package/build/lib/helpers/network.js +35 -0
- package/build/lib/helpers/network.js.map +1 -0
- package/build/lib/insecure-features.js +6 -6
- package/build/lib/insecure-features.js.map +1 -1
- package/build/lib/inspector-commands.d.ts +6 -0
- package/build/lib/inspector-commands.d.ts.map +1 -1
- package/build/lib/inspector-commands.js +6 -0
- package/build/lib/inspector-commands.js.map +1 -1
- package/build/lib/logger.d.ts +2 -3
- package/build/lib/logger.d.ts.map +1 -1
- package/build/lib/logger.js +2 -3
- package/build/lib/logger.js.map +1 -1
- package/build/lib/logsink.d.ts +13 -22
- package/build/lib/logsink.d.ts.map +1 -1
- package/build/lib/logsink.js +48 -103
- package/build/lib/logsink.js.map +1 -1
- package/build/lib/main.d.ts +15 -58
- package/build/lib/main.d.ts.map +1 -1
- package/build/lib/main.js +25 -425
- package/build/lib/main.js.map +1 -1
- package/build/lib/schema/arg-spec.d.ts +32 -107
- package/build/lib/schema/arg-spec.d.ts.map +1 -1
- package/build/lib/schema/arg-spec.js +11 -107
- package/build/lib/schema/arg-spec.js.map +1 -1
- package/build/lib/schema/cli-args-guards.d.ts +34 -0
- package/build/lib/schema/cli-args-guards.d.ts.map +1 -0
- package/build/lib/schema/cli-args-guards.js +49 -0
- package/build/lib/schema/cli-args-guards.js.map +1 -0
- package/build/lib/schema/cli-args.d.ts +3 -15
- package/build/lib/schema/cli-args.d.ts.map +1 -1
- package/build/lib/schema/cli-args.js +17 -107
- package/build/lib/schema/cli-args.js.map +1 -1
- package/build/lib/schema/cli-transformers.d.ts +15 -12
- package/build/lib/schema/cli-transformers.d.ts.map +1 -1
- package/build/lib/schema/cli-transformers.js +15 -45
- package/build/lib/schema/cli-transformers.js.map +1 -1
- package/build/lib/schema/format-errors.d.ts +28 -0
- package/build/lib/schema/format-errors.d.ts.map +1 -0
- package/build/lib/schema/format-errors.js +29 -0
- package/build/lib/schema/format-errors.js.map +1 -0
- package/build/lib/schema/index.d.ts +4 -2
- package/build/lib/schema/index.d.ts.map +1 -1
- package/build/lib/schema/index.js +2 -0
- package/build/lib/schema/index.js.map +1 -1
- package/build/lib/schema/keywords.d.ts +12 -20
- package/build/lib/schema/keywords.d.ts.map +1 -1
- package/build/lib/schema/keywords.js +6 -51
- package/build/lib/schema/keywords.js.map +1 -1
- package/build/lib/schema/schema.d.ts +106 -231
- package/build/lib/schema/schema.d.ts.map +1 -1
- package/build/lib/schema/schema.js +88 -358
- package/build/lib/schema/schema.js.map +1 -1
- package/build/lib/utils.d.ts +7 -267
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +10 -409
- package/build/lib/utils.js.map +1 -1
- package/lib/{appium.js → appium.ts} +297 -341
- package/lib/bidi-commands.ts +10 -14
- package/lib/bootstrap/appium-initializer.ts +212 -0
- package/lib/bootstrap/appium-main-runner.ts +172 -0
- package/lib/bootstrap/config-file.ts +178 -0
- package/lib/bootstrap/grid-v3-register.ts +250 -0
- package/lib/bootstrap/init-types.ts +31 -0
- package/lib/bootstrap/main-helpers.ts +223 -0
- package/lib/bootstrap/node-helpers.ts +180 -0
- package/lib/bootstrap/startup-config.ts +143 -0
- package/lib/cli/{args.js → args.ts} +45 -56
- package/lib/cli/driver-command.ts +122 -0
- package/lib/cli/{extension-command.js → extension-command.ts} +827 -906
- package/lib/cli/extension.ts +65 -0
- package/lib/cli/{parser.js → parser.ts} +93 -116
- package/lib/cli/plugin-command.ts +117 -0
- package/lib/cli/{setup-command.js → setup-command.ts} +59 -74
- package/lib/cli/utils.ts +97 -0
- package/lib/{constants.js → constants.ts} +30 -41
- package/lib/doctor/{doctor.js → doctor.ts} +82 -92
- package/lib/extension/driver-config.ts +165 -0
- package/lib/extension/{extension-config.js → extension-config.ts} +291 -405
- package/lib/extension/index.ts +143 -0
- package/lib/extension/manifest-migrations.ts +57 -0
- package/lib/extension/manifest.ts +369 -0
- package/lib/extension/{package-changed.js → package-changed.ts} +9 -18
- package/lib/extension/plugin-config.ts +62 -0
- package/lib/helpers/build.ts +111 -0
- package/lib/helpers/capability.ts +171 -0
- package/lib/helpers/network.ts +30 -0
- package/lib/insecure-features.ts +1 -1
- package/lib/inspector-commands.ts +6 -1
- package/lib/{logger.js → logger.ts} +1 -2
- package/lib/{logsink.js → logsink.ts} +91 -137
- package/lib/main.ts +60 -0
- package/lib/schema/arg-spec.ts +131 -0
- package/lib/schema/cli-args-guards.ts +67 -0
- package/lib/schema/cli-args.ts +171 -0
- package/lib/schema/cli-transformers.ts +83 -0
- package/lib/schema/format-errors.ts +43 -0
- package/lib/schema/index.ts +4 -0
- package/lib/schema/keywords.ts +96 -0
- package/lib/schema/schema.ts +448 -0
- package/lib/utils.ts +73 -0
- package/package.json +17 -18
- package/scripts/autoinstall-extensions.js +3 -0
- package/build/lib/config-file.d.ts +0 -100
- package/build/lib/config-file.d.ts.map +0 -1
- package/build/lib/config-file.js.map +0 -1
- package/build/lib/config.d.ts +0 -70
- package/build/lib/config.d.ts.map +0 -1
- package/build/lib/config.js +0 -390
- package/build/lib/config.js.map +0 -1
- package/build/lib/grid-register.d.ts +0 -10
- package/build/lib/grid-register.d.ts.map +0 -1
- package/build/lib/grid-register.js +0 -134
- package/build/lib/grid-register.js.map +0 -1
- package/lib/cli/driver-command.js +0 -174
- package/lib/cli/extension.js +0 -74
- package/lib/cli/plugin-command.js +0 -164
- package/lib/cli/utils.js +0 -91
- package/lib/config-file.js +0 -228
- package/lib/config.js +0 -389
- package/lib/extension/driver-config.js +0 -245
- package/lib/extension/index.js +0 -169
- package/lib/extension/manifest-migrations.js +0 -136
- package/lib/extension/manifest.js +0 -550
- package/lib/extension/plugin-config.js +0 -112
- package/lib/grid-register.js +0 -146
- package/lib/main.js +0 -545
- package/lib/schema/arg-spec.js +0 -229
- package/lib/schema/cli-args.js +0 -254
- package/lib/schema/cli-transformers.js +0 -113
- package/lib/schema/index.js +0 -2
- package/lib/schema/keywords.js +0 -136
- package/lib/schema/schema.js +0 -725
- package/lib/utils.js +0 -512
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import type {Class, DriverType, ExtensionType, PluginType} from '@appium/types';
|
|
3
|
+
import type {Args, CliExtensionCommand, CliExtensionSubcommand} from 'appium/types';
|
|
4
|
+
import type {ExtensionConfig} from '../extension/extension-config';
|
|
5
|
+
import {DRIVER_TYPE, PLUGIN_TYPE} from '../constants';
|
|
6
|
+
import {isExtensionCommandArgs} from '../schema/cli-args-guards';
|
|
7
|
+
import DriverCliCommand from './driver-command';
|
|
8
|
+
import PluginCliCommand from './plugin-command';
|
|
9
|
+
import {errAndQuit, JSON_SPACES} from './utils';
|
|
10
|
+
|
|
11
|
+
export const commandClasses = Object.freeze(
|
|
12
|
+
{
|
|
13
|
+
[DRIVER_TYPE]: DriverCliCommand,
|
|
14
|
+
[PLUGIN_TYPE]: PluginCliCommand,
|
|
15
|
+
} as const
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
export type ExtCommand<ExtType extends ExtensionType> = ExtType extends DriverType
|
|
19
|
+
? Class<DriverCliCommand>
|
|
20
|
+
: ExtType extends PluginType
|
|
21
|
+
? Class<PluginCliCommand>
|
|
22
|
+
: never;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Executes a driver/plugin extension subcommand and returns the command result.
|
|
26
|
+
*
|
|
27
|
+
* When JSON output is enabled, this also prints the serialized command result
|
|
28
|
+
* unless output was suppressed by the caller.
|
|
29
|
+
*/
|
|
30
|
+
export async function runExtensionCommand<
|
|
31
|
+
Cmd extends CliExtensionCommand,
|
|
32
|
+
SubCmd extends CliExtensionSubcommand,
|
|
33
|
+
>(args: Args<Cmd, SubCmd>, config: ExtensionConfig<Cmd>) {
|
|
34
|
+
// TODO driver config file should be locked while any of these commands are
|
|
35
|
+
// running to prevent weird situations
|
|
36
|
+
let jsonResult: Record<string, unknown> = {};
|
|
37
|
+
const {extensionType: type} = config; // NOTE this is the same as `args.subcommand`
|
|
38
|
+
if (!isExtensionCommandArgs(args)) {
|
|
39
|
+
throw new TypeError(`Cannot call ${type} command without a subcommand like 'install'`);
|
|
40
|
+
}
|
|
41
|
+
let {json} = args;
|
|
42
|
+
const {suppressOutput} = args;
|
|
43
|
+
json = Boolean(json);
|
|
44
|
+
if (suppressOutput) {
|
|
45
|
+
json = true;
|
|
46
|
+
}
|
|
47
|
+
const CommandClass = commandClasses[type] as ExtCommand<Cmd>;
|
|
48
|
+
const cmd = new CommandClass({config, json} as any);
|
|
49
|
+
try {
|
|
50
|
+
jsonResult = (await cmd.execute(args)) as Record<string, unknown>;
|
|
51
|
+
} catch (err) {
|
|
52
|
+
// in the suppress output case, we are calling this function internally and should
|
|
53
|
+
// just throw instead of printing an error and ending the process
|
|
54
|
+
if (suppressOutput) {
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
errAndQuit(json, err);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (json && !suppressOutput) {
|
|
61
|
+
console.log(JSON.stringify(jsonResult, null, JSON_SPACES));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return jsonResult;
|
|
65
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import {fs} from '@appium/support';
|
|
2
2
|
import {ArgumentParser} from 'argparse';
|
|
3
|
+
import type {SubArgumentParserOptions, SubParser} from 'argparse';
|
|
3
4
|
import _ from 'lodash';
|
|
4
5
|
import path from 'node:path';
|
|
6
|
+
import type {DriverType, PluginType} from '@appium/types';
|
|
7
|
+
import type {CliExtensionSubcommand} from 'appium/types';
|
|
5
8
|
import {
|
|
6
9
|
DRIVER_TYPE,
|
|
7
10
|
EXT_SUBCOMMAND_DOCTOR,
|
|
@@ -15,8 +18,9 @@ import {
|
|
|
15
18
|
SETUP_SUBCOMMAND
|
|
16
19
|
} from '../constants';
|
|
17
20
|
import {finalizeSchema, getAllArgSpecs, getArgSpec, hasArgSpec} from '../schema';
|
|
18
|
-
import {rootDir} from '../
|
|
21
|
+
import {rootDir} from '../helpers/build';
|
|
19
22
|
import {getExtensionArgs, getServerArgs} from './args';
|
|
23
|
+
import type {ArgumentDefinitions} from './args';
|
|
20
24
|
import {
|
|
21
25
|
DEFAULT_PLUGINS,
|
|
22
26
|
SUBCOMMAND_MOBILE,
|
|
@@ -38,6 +42,8 @@ const NON_SERVER_ARGS = Object.freeze(
|
|
|
38
42
|
);
|
|
39
43
|
|
|
40
44
|
const version = fs.readPackageJsonFrom(rootDir).version;
|
|
45
|
+
type LooseArgsMap = {[key: string]: any};
|
|
46
|
+
type TransformedArgsMap = LooseArgsMap & {[EXTRA_ARGS]: string[]};
|
|
41
47
|
|
|
42
48
|
/**
|
|
43
49
|
* A wrapper around `argparse`
|
|
@@ -46,9 +52,15 @@ const version = fs.readPackageJsonFrom(rootDir).version;
|
|
|
46
52
|
* `ArgumentParser` instance for Appium server and its extensions
|
|
47
53
|
* - Handles error conditions, messages, and exit behavior
|
|
48
54
|
*/
|
|
49
|
-
class ArgParser {
|
|
55
|
+
export class ArgParser {
|
|
56
|
+
readonly prog: string;
|
|
57
|
+
readonly debug: boolean;
|
|
58
|
+
readonly parser: ArgumentParser;
|
|
59
|
+
readonly rawArgs: ArgumentDefinitions;
|
|
60
|
+
readonly parse_args: ArgParser['parseArgs'];
|
|
61
|
+
|
|
50
62
|
/**
|
|
51
|
-
* @param
|
|
63
|
+
* @param debug - if true, throw instead of exiting on parse errors
|
|
52
64
|
*/
|
|
53
65
|
constructor(debug = false) {
|
|
54
66
|
const prog = process.argv[1] ? path.basename(process.argv[1]) : 'appium';
|
|
@@ -62,22 +74,10 @@ class ArgParser {
|
|
|
62
74
|
|
|
63
75
|
ArgParser._patchExit(parser);
|
|
64
76
|
|
|
65
|
-
/**
|
|
66
|
-
* Program name (typically `appium`)
|
|
67
|
-
* @type {string}
|
|
68
|
-
*/
|
|
69
77
|
this.prog = prog;
|
|
70
78
|
|
|
71
|
-
/**
|
|
72
|
-
* If `true`, throw an error on parse failure instead of printing help
|
|
73
|
-
* @type {boolean}
|
|
74
|
-
*/
|
|
75
79
|
this.debug = debug;
|
|
76
80
|
|
|
77
|
-
/**
|
|
78
|
-
* Wrapped `ArgumentParser` instance
|
|
79
|
-
* @type {ArgumentParser}
|
|
80
|
-
*/
|
|
81
81
|
this.parser = parser;
|
|
82
82
|
|
|
83
83
|
parser.add_argument('-v', '--version', {
|
|
@@ -101,77 +101,20 @@ class ArgParser {
|
|
|
101
101
|
ArgParser._addSetupToParser(subParsers);
|
|
102
102
|
|
|
103
103
|
// backwards compatibility / drop-in wrapper
|
|
104
|
-
/**
|
|
105
|
-
* @type {ArgParser['parseArgs']}
|
|
106
|
-
*/
|
|
107
104
|
this.parse_args = this.parseArgs;
|
|
108
105
|
}
|
|
109
106
|
|
|
110
107
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* If no subcommand is passed in, this method will inject the `server` subcommand.
|
|
108
|
+
* Normalizes server arg keys from schema names to parser destination names.
|
|
114
109
|
*
|
|
115
|
-
*
|
|
116
|
-
* @template {import('appium/types').CliCommand} [Cmd=import('appium/types').CliCommandServer]
|
|
117
|
-
* @param {string[]} [args] - Array of arguments, ostensibly from `process.argv`. Gathers args from `process.argv` if not provided.
|
|
118
|
-
* @returns {import('appium/types').Args<Cmd>} - The parsed arguments
|
|
110
|
+
* This mutates and returns the same object.
|
|
119
111
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
args.unshift(SERVER_SUBCOMMAND);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const parsed = this.parser.parse_known_args(args);
|
|
127
|
-
const [knownArgs, unknownArgs] = parsed;
|
|
128
|
-
// XXX: you'd think that argparse, when given an alias for a subcommand,
|
|
129
|
-
// would set this value to the original subcommand name, but it doesn't.
|
|
130
|
-
if (knownArgs?.driverCommand === 'ls') {
|
|
131
|
-
knownArgs.driverCommand = 'list';
|
|
132
|
-
} else if (knownArgs?.pluginCommand === 'ls') {
|
|
133
|
-
knownArgs.pluginCommand = 'list';
|
|
134
|
-
}
|
|
135
|
-
if (
|
|
136
|
-
unknownArgs?.length &&
|
|
137
|
-
(knownArgs.driverCommand === 'run' || knownArgs.pluginCommand === 'run')
|
|
138
|
-
) {
|
|
139
|
-
return ArgParser._transformParsedArgs(knownArgs, unknownArgs);
|
|
140
|
-
} else if (unknownArgs?.length) {
|
|
141
|
-
throw new Error(`[ERROR] Unrecognized arguments: ${unknownArgs.join(' ')}`);
|
|
142
|
-
}
|
|
143
|
-
return ArgParser._transformParsedArgs(knownArgs);
|
|
144
|
-
} catch (err) {
|
|
145
|
-
if (this.debug) {
|
|
146
|
-
throw err;
|
|
147
|
-
}
|
|
148
|
-
// this isn't tested via unit tests (we use `debug: true`) so may escape coverage.
|
|
149
|
-
|
|
150
|
-
/* istanbul ignore next */
|
|
151
|
-
{
|
|
152
|
-
// eslint-disable-next-line no-console
|
|
153
|
-
console.error(); // need an extra space since argparse prints usage.
|
|
154
|
-
// eslint-disable-next-line no-console
|
|
155
|
-
console.error(err.message);
|
|
156
|
-
process.exit(1);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Normalize hyphenated server arg keys (e.g. "log-level") to dest form (e.g. "loglevel").
|
|
163
|
-
* Use when server args come from programmatic init rather than the CLI, so they match
|
|
164
|
-
* the shape produced by parseArgs() / _transformParsedArgs().
|
|
165
|
-
* Mutates the given object.
|
|
166
|
-
*
|
|
167
|
-
* @param {object} obj - Object that may contain server args with schema property names
|
|
168
|
-
* @returns {object} The same object with keys normalized
|
|
169
|
-
*/
|
|
170
|
-
static normalizeServerArgs(obj) {
|
|
112
|
+
static normalizeServerArgs<T extends LooseArgsMap>(obj: T): T {
|
|
113
|
+
const mutableObj = obj as LooseArgsMap;
|
|
171
114
|
for (const spec of getAllArgSpecs().values()) {
|
|
172
|
-
if (!spec.extType &&
|
|
173
|
-
|
|
174
|
-
delete
|
|
115
|
+
if (!spec.extType && mutableObj[spec.name] !== undefined && spec.rawDest !== spec.name) {
|
|
116
|
+
mutableObj[spec.rawDest] = mutableObj[spec.name] ?? mutableObj[spec.rawDest];
|
|
117
|
+
delete mutableObj[spec.name];
|
|
175
118
|
}
|
|
176
119
|
}
|
|
177
120
|
return obj;
|
|
@@ -183,16 +126,17 @@ class ArgParser {
|
|
|
183
126
|
* keys to match the intended destination.
|
|
184
127
|
*
|
|
185
128
|
* E.g., `{'driver-foo-bar': baz}` becomes `{driver: {foo: {bar: 'baz'}}}`
|
|
186
|
-
* @param {object} args
|
|
187
|
-
* @param {string[]} [unknownArgs]
|
|
188
|
-
* @returns {object}
|
|
189
129
|
*/
|
|
190
|
-
static _transformParsedArgs(
|
|
130
|
+
private static _transformParsedArgs(
|
|
131
|
+
args: LooseArgsMap,
|
|
132
|
+
unknownArgs: string[] = []
|
|
133
|
+
): TransformedArgsMap {
|
|
191
134
|
const result = _.reduce(
|
|
192
135
|
args,
|
|
193
136
|
(unpacked, value, key) => {
|
|
194
|
-
|
|
195
|
-
|
|
137
|
+
const spec = hasArgSpec(key) ? getArgSpec(key) : undefined;
|
|
138
|
+
if (!_.isUndefined(value) && spec) {
|
|
139
|
+
const {dest} = spec;
|
|
196
140
|
_.set(unpacked, dest, value);
|
|
197
141
|
} else {
|
|
198
142
|
// this could be anything that _isn't_ a server arg
|
|
@@ -203,14 +147,13 @@ class ArgParser {
|
|
|
203
147
|
{}
|
|
204
148
|
);
|
|
205
149
|
result[EXTRA_ARGS] = unknownArgs;
|
|
206
|
-
return result;
|
|
150
|
+
return result as TransformedArgsMap;
|
|
207
151
|
}
|
|
208
152
|
|
|
209
153
|
/**
|
|
210
154
|
* Patches the `exit()` method of the parser to throw an error, so we can handle it manually.
|
|
211
|
-
* @param {ArgumentParser} parser
|
|
212
155
|
*/
|
|
213
|
-
static _patchExit(parser) {
|
|
156
|
+
private static _patchExit(parser: ArgumentParser): void {
|
|
214
157
|
parser.exit = (code, msg) => {
|
|
215
158
|
if (code) {
|
|
216
159
|
throw new Error(msg);
|
|
@@ -220,11 +163,9 @@ class ArgParser {
|
|
|
220
163
|
}
|
|
221
164
|
|
|
222
165
|
/**
|
|
223
|
-
*
|
|
224
|
-
* @param {import('argparse').SubParser} subParser
|
|
225
|
-
* @returns {import('./args').ArgumentDefinitions}
|
|
166
|
+
* Adds the `server` subcommand parser and returns its argument definitions.
|
|
226
167
|
*/
|
|
227
|
-
static _addServerToParser(subParser) {
|
|
168
|
+
private static _addServerToParser(subParser: SubParser): ArgumentDefinitions {
|
|
228
169
|
const serverParser = subParser.add_parser('server', {
|
|
229
170
|
add_help: true,
|
|
230
171
|
help: 'Start an Appium server',
|
|
@@ -244,11 +185,10 @@ class ArgParser {
|
|
|
244
185
|
|
|
245
186
|
/**
|
|
246
187
|
* Adds extension sub-sub-commands to `driver`/`plugin` subcommands
|
|
247
|
-
* @param {import('argparse').SubParser} subParsers
|
|
248
188
|
*/
|
|
249
|
-
static _addExtensionCommandsToParser(
|
|
250
|
-
for (const type of
|
|
251
|
-
const extParser =
|
|
189
|
+
private static _addExtensionCommandsToParser(subParser: SubParser): void {
|
|
190
|
+
for (const type of [DRIVER_TYPE, PLUGIN_TYPE] as [DriverType, PluginType]) {
|
|
191
|
+
const extParser = subParser.add_parser(type, {
|
|
252
192
|
add_help: true,
|
|
253
193
|
help: `Manage Appium ${type}s`,
|
|
254
194
|
description: `Manage Appium ${type}s using various subcommands`,
|
|
@@ -260,10 +200,12 @@ class ArgParser {
|
|
|
260
200
|
dest: `${type}Command`,
|
|
261
201
|
});
|
|
262
202
|
const extensionArgs = getExtensionArgs();
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
203
|
+
const parserSpecs: {
|
|
204
|
+
command: CliExtensionSubcommand;
|
|
205
|
+
args: ArgumentDefinitions;
|
|
206
|
+
help: string;
|
|
207
|
+
aliases?: SubArgumentParserOptions['aliases'];
|
|
208
|
+
}[] = [
|
|
267
209
|
{
|
|
268
210
|
command: EXT_SUBCOMMAND_LIST,
|
|
269
211
|
args: extensionArgs[type].list,
|
|
@@ -316,9 +258,8 @@ class ArgParser {
|
|
|
316
258
|
|
|
317
259
|
/**
|
|
318
260
|
* Add subcommand and sub-sub commands for 'setup' subcommand.
|
|
319
|
-
* @param {import('argparse').SubParser} subParser
|
|
320
261
|
*/
|
|
321
|
-
static _addSetupToParser(subParser) {
|
|
262
|
+
private static _addSetupToParser(subParser: SubParser): void {
|
|
322
263
|
const setupParser = subParser.add_parser('setup', {
|
|
323
264
|
add_help: true,
|
|
324
265
|
help: 'Batch install or uninstall Appium drivers and plugins',
|
|
@@ -365,24 +306,60 @@ class ArgParser {
|
|
|
365
306
|
ArgParser._patchExit(parser);
|
|
366
307
|
}
|
|
367
308
|
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Parses CLI args and returns Appium's normalized argument object.
|
|
312
|
+
*
|
|
313
|
+
* If no explicit subcommand is provided, this injects `server`.
|
|
314
|
+
* `parse_args` is a backwards-compatible alias of this method.
|
|
315
|
+
*/
|
|
316
|
+
parseArgs(args: string[] = process.argv.slice(2)): TransformedArgsMap {
|
|
317
|
+
if (!NON_SERVER_ARGS.has(args[0])) {
|
|
318
|
+
args.unshift(SERVER_SUBCOMMAND);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
try {
|
|
322
|
+
const parsed = this.parser.parse_known_args(args);
|
|
323
|
+
const [knownArgs, unknownArgs] = parsed;
|
|
324
|
+
// XXX: you'd think that argparse, when given an alias for a subcommand,
|
|
325
|
+
// would set this value to the original subcommand name, but it doesn't.
|
|
326
|
+
if (knownArgs?.driverCommand === 'ls') {
|
|
327
|
+
knownArgs.driverCommand = 'list';
|
|
328
|
+
} else if (knownArgs?.pluginCommand === 'ls') {
|
|
329
|
+
knownArgs.pluginCommand = 'list';
|
|
330
|
+
}
|
|
331
|
+
if (
|
|
332
|
+
unknownArgs?.length &&
|
|
333
|
+
(knownArgs.driverCommand === 'run' || knownArgs.pluginCommand === 'run')
|
|
334
|
+
) {
|
|
335
|
+
return ArgParser._transformParsedArgs(knownArgs, unknownArgs);
|
|
336
|
+
} else if (unknownArgs?.length) {
|
|
337
|
+
throw new Error(`[ERROR] Unrecognized arguments: ${unknownArgs.join(' ')}`);
|
|
338
|
+
}
|
|
339
|
+
return ArgParser._transformParsedArgs(knownArgs);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
if (this.debug) {
|
|
342
|
+
throw err;
|
|
343
|
+
}
|
|
344
|
+
// this isn't tested via unit tests (we use `debug: true`) so may escape coverage.
|
|
345
|
+
|
|
346
|
+
/* istanbul ignore next */
|
|
347
|
+
{
|
|
348
|
+
// eslint-disable-next-line no-console
|
|
349
|
+
console.error(); // need an extra space since argparse prints usage.
|
|
350
|
+
// eslint-disable-next-line no-console
|
|
351
|
+
console.error(err.message);
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
368
356
|
}
|
|
369
357
|
|
|
370
358
|
/**
|
|
371
|
-
* Creates
|
|
372
|
-
*
|
|
373
|
-
* @constructs ArgParser
|
|
374
|
-
* @param {boolean} [debug] - If `true`, throw instead of exit upon parsing error
|
|
375
|
-
* @returns {ArgParser}
|
|
359
|
+
* Creates and returns an `ArgParser` after finalizing schema state.
|
|
376
360
|
*/
|
|
377
|
-
function getParser(debug) {
|
|
378
|
-
finalizeSchema();
|
|
361
|
+
export async function getParser(debug = false): Promise<ArgParser> {
|
|
362
|
+
await finalizeSchema();
|
|
379
363
|
|
|
380
364
|
return new ArgParser(debug);
|
|
381
365
|
}
|
|
382
|
-
|
|
383
|
-
export {getParser, ArgParser};
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* @typedef {import('@appium/types').DriverType} DriverType
|
|
387
|
-
* @typedef {import('@appium/types').PluginType} PluginType
|
|
388
|
-
*/
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import type {ExtMetadata, ExtRecord, InstallType} from 'appium/types';
|
|
3
|
+
import ExtensionCliCommand from './extension-command';
|
|
4
|
+
import type {
|
|
5
|
+
ExtensionArgs,
|
|
6
|
+
ExtensionCommandOptions,
|
|
7
|
+
ExtensionUpdateResult,
|
|
8
|
+
PostInstallText,
|
|
9
|
+
RunOutput,
|
|
10
|
+
} from './extension-command';
|
|
11
|
+
import {KNOWN_PLUGINS} from '../constants';
|
|
12
|
+
|
|
13
|
+
const REQ_PLUGIN_FIELDS = ['pluginName', 'mainClass'];
|
|
14
|
+
type PluginInstallOpts = {plugin: string; installType: InstallType; packageName?: string};
|
|
15
|
+
type PluginUninstallOpts = {plugin: string};
|
|
16
|
+
type PluginUpdateOpts = {plugin: string; unsafe: boolean};
|
|
17
|
+
type PluginRunOptions = {plugin: string; scriptName: string; extraArgs?: string[]};
|
|
18
|
+
type PluginDoctorOptions = {plugin: string};
|
|
19
|
+
|
|
20
|
+
export default class PluginCliCommand extends ExtensionCliCommand<'plugin'> {
|
|
21
|
+
constructor({config, json}: ExtensionCommandOptions<'plugin'>) {
|
|
22
|
+
super({config, json});
|
|
23
|
+
this.knownExtensions = KNOWN_PLUGINS;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Install a plugin
|
|
28
|
+
*
|
|
29
|
+
* @param opts - install options
|
|
30
|
+
*/
|
|
31
|
+
async install({plugin, installType, packageName}: PluginInstallOpts): Promise<ExtRecord<'plugin'>> {
|
|
32
|
+
return await super._install({
|
|
33
|
+
installSpec: plugin,
|
|
34
|
+
installType,
|
|
35
|
+
packageName,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Uninstall a plugin
|
|
41
|
+
*
|
|
42
|
+
* @param opts - uninstall options
|
|
43
|
+
*/
|
|
44
|
+
async uninstall({plugin}: PluginUninstallOpts): Promise<ExtRecord<'plugin'>> {
|
|
45
|
+
return await super._uninstall({installSpec: plugin});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Update a plugin
|
|
50
|
+
*
|
|
51
|
+
* @param opts - update options
|
|
52
|
+
*/
|
|
53
|
+
async update({plugin, unsafe}: PluginUpdateOpts): Promise<ExtensionUpdateResult> {
|
|
54
|
+
return await super._update({installSpec: plugin, unsafe});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Run a script from a plugin
|
|
59
|
+
*
|
|
60
|
+
* @param opts - script execution options
|
|
61
|
+
* @throws {Error} if the script fails to run
|
|
62
|
+
*/
|
|
63
|
+
async run({plugin, scriptName, extraArgs}: PluginRunOptions): Promise<RunOutput> {
|
|
64
|
+
return await super._run({
|
|
65
|
+
installSpec: plugin,
|
|
66
|
+
scriptName,
|
|
67
|
+
extraArgs,
|
|
68
|
+
bufferOutput: this.isJsonOutput,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Runs doctor checks for the given plugin
|
|
74
|
+
*
|
|
75
|
+
* @param opts - doctor command options
|
|
76
|
+
* @returns The amount of executed doctor checks.
|
|
77
|
+
* @throws {Error} If any of the mandatory Doctor checks fails.
|
|
78
|
+
*/
|
|
79
|
+
async doctor({plugin}: PluginDoctorOptions): Promise<number> {
|
|
80
|
+
return await super._doctor({
|
|
81
|
+
installSpec: plugin,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Builds the success message displayed after a plugin installation.
|
|
87
|
+
*
|
|
88
|
+
* @param args - installed extension name and metadata
|
|
89
|
+
* @returns formatted success text
|
|
90
|
+
*/
|
|
91
|
+
override getPostInstallText({extName, extData}: ExtensionArgs<'plugin'>): PostInstallText {
|
|
92
|
+
return `Plugin ${extName}@${extData.version} successfully installed`.green;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Validates fields in `appium` field of `pluginMetadata`
|
|
97
|
+
*
|
|
98
|
+
* For any `package.json` fields which a plugin requires, validate the type of
|
|
99
|
+
* those fields on the `package.json` data, throwing an error if anything is
|
|
100
|
+
* amiss.
|
|
101
|
+
* @param pluginMetadata - `appium` metadata from extension package
|
|
102
|
+
* @param installSpec - install spec from CLI
|
|
103
|
+
*/
|
|
104
|
+
override validateExtensionFields(pluginMetadata: ExtMetadata<'plugin'>, installSpec: string): void {
|
|
105
|
+
const missingFields = REQ_PLUGIN_FIELDS.reduce(
|
|
106
|
+
(acc, field) => (pluginMetadata[field] ? acc : [...acc, field]),
|
|
107
|
+
[]
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
if (!_.isEmpty(missingFields)) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Installed plugin "${installSpec}" did not expose correct fields for compatibility ` +
|
|
113
|
+
`with Appium. Missing fields: ${JSON.stringify(missingFields)}`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|