appium 2.0.0-beta.9 → 2.0.0-rc.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/LICENSE +1 -1
- package/README.md +149 -58
- package/build/lib/appium.d.ts +229 -0
- package/build/lib/appium.d.ts.map +1 -0
- package/build/lib/appium.js +677 -449
- package/build/lib/appium.js.map +1 -0
- package/build/lib/cli/args.d.ts +17 -0
- package/build/lib/cli/args.d.ts.map +1 -0
- package/build/lib/cli/args.js +263 -300
- package/build/lib/cli/args.js.map +1 -0
- package/build/lib/cli/driver-command.d.ts +102 -0
- package/build/lib/cli/driver-command.d.ts.map +1 -0
- package/build/lib/cli/driver-command.js +131 -81
- package/build/lib/cli/driver-command.js.map +1 -0
- package/build/lib/cli/extension-command.d.ts +402 -0
- package/build/lib/cli/extension-command.d.ts.map +1 -0
- package/build/lib/cli/extension-command.js +799 -383
- package/build/lib/cli/extension-command.js.map +1 -0
- package/build/lib/cli/extension.d.ts +23 -0
- package/build/lib/cli/extension.d.ts.map +1 -0
- package/build/lib/cli/extension.js +70 -68
- package/build/lib/cli/extension.js.map +1 -0
- package/build/lib/cli/parser.d.ts +84 -0
- package/build/lib/cli/parser.d.ts.map +1 -0
- package/build/lib/cli/parser.js +252 -148
- package/build/lib/cli/parser.js.map +1 -0
- package/build/lib/cli/plugin-command.d.ts +99 -0
- package/build/lib/cli/plugin-command.d.ts.map +1 -0
- package/build/lib/cli/plugin-command.js +125 -81
- package/build/lib/cli/plugin-command.js.map +1 -0
- package/build/lib/cli/utils.d.ts +29 -0
- package/build/lib/cli/utils.d.ts.map +1 -0
- package/build/lib/cli/utils.js +72 -51
- package/build/lib/cli/utils.js.map +1 -0
- package/build/lib/config-file.d.ts +100 -0
- package/build/lib/config-file.d.ts.map +1 -0
- package/build/lib/config-file.js +207 -0
- package/build/lib/config-file.js.map +1 -0
- package/build/lib/config.d.ts +49 -0
- package/build/lib/config.d.ts.map +1 -0
- package/build/lib/config.js +262 -223
- package/build/lib/config.js.map +1 -0
- package/build/lib/constants.d.ts +56 -0
- package/build/lib/constants.d.ts.map +1 -0
- package/build/lib/constants.js +73 -0
- package/build/lib/constants.js.map +1 -0
- package/build/lib/extension/driver-config.d.ts +82 -0
- package/build/lib/extension/driver-config.d.ts.map +1 -0
- package/build/lib/extension/driver-config.js +210 -0
- package/build/lib/extension/driver-config.js.map +1 -0
- package/build/lib/extension/extension-config.d.ts +270 -0
- package/build/lib/extension/extension-config.d.ts.map +1 -0
- package/build/lib/extension/extension-config.js +601 -0
- package/build/lib/extension/extension-config.js.map +1 -0
- package/build/lib/extension/index.d.ts +48 -0
- package/build/lib/extension/index.d.ts.map +1 -0
- package/build/lib/extension/index.js +105 -0
- package/build/lib/extension/index.js.map +1 -0
- package/build/lib/extension/manifest-migrations.d.ts +27 -0
- package/build/lib/extension/manifest-migrations.d.ts.map +1 -0
- package/build/lib/extension/manifest-migrations.js +134 -0
- package/build/lib/extension/manifest-migrations.js.map +1 -0
- package/build/lib/extension/manifest.d.ts +145 -0
- package/build/lib/extension/manifest.d.ts.map +1 -0
- package/build/lib/extension/manifest.js +528 -0
- package/build/lib/extension/manifest.js.map +1 -0
- package/build/lib/extension/package-changed.d.ts +11 -0
- package/build/lib/extension/package-changed.d.ts.map +1 -0
- package/build/lib/extension/package-changed.js +62 -0
- package/build/lib/extension/package-changed.js.map +1 -0
- package/build/lib/extension/plugin-config.d.ts +56 -0
- package/build/lib/extension/plugin-config.d.ts.map +1 -0
- package/build/lib/extension/plugin-config.js +102 -0
- package/build/lib/extension/plugin-config.js.map +1 -0
- package/build/lib/grid-register.d.ts +10 -0
- package/build/lib/grid-register.d.ts.map +1 -0
- package/build/lib/grid-register.js +122 -144
- package/build/lib/grid-register.js.map +1 -0
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logger.js +5 -17
- package/build/lib/logger.js.map +1 -0
- package/build/lib/logsink.d.ts +4 -0
- package/build/lib/logsink.d.ts.map +1 -0
- package/build/lib/logsink.js +189 -184
- package/build/lib/logsink.js.map +1 -0
- package/build/lib/main.d.ts +62 -0
- package/build/lib/main.d.ts.map +1 -0
- package/build/lib/main.js +406 -234
- package/build/lib/main.js.map +1 -0
- package/build/lib/schema/arg-spec.d.ts +143 -0
- package/build/lib/schema/arg-spec.d.ts.map +1 -0
- package/build/lib/schema/arg-spec.js +164 -0
- package/build/lib/schema/arg-spec.js.map +1 -0
- package/build/lib/schema/cli-args.d.ts +19 -0
- package/build/lib/schema/cli-args.d.ts.map +1 -0
- package/build/lib/schema/cli-args.js +220 -0
- package/build/lib/schema/cli-args.js.map +1 -0
- package/build/lib/schema/cli-transformers.d.ts +5 -0
- package/build/lib/schema/cli-transformers.d.ts.map +1 -0
- package/build/lib/schema/cli-transformers.js +124 -0
- package/build/lib/schema/cli-transformers.js.map +1 -0
- package/build/lib/schema/index.d.ts +3 -0
- package/build/lib/schema/index.d.ts.map +1 -0
- package/build/lib/schema/index.js +19 -0
- package/build/lib/schema/index.js.map +1 -0
- package/build/lib/schema/keywords.d.ts +24 -0
- package/build/lib/schema/keywords.d.ts.map +1 -0
- package/build/lib/schema/keywords.js +128 -0
- package/build/lib/schema/keywords.js.map +1 -0
- package/build/lib/schema/schema.d.ts +260 -0
- package/build/lib/schema/schema.d.ts.map +1 -0
- package/build/lib/schema/schema.js +640 -0
- package/build/lib/schema/schema.js.map +1 -0
- package/build/lib/utils.d.ts +276 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.js +372 -192
- package/build/lib/utils.js.map +1 -0
- package/build/types/cli.d.ts +134 -0
- package/build/types/cli.d.ts.map +1 -0
- package/build/types/cli.js +3 -0
- package/build/types/cli.js.map +1 -0
- package/build/types/index.d.ts +15 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/index.js +19 -0
- package/build/types/index.js.map +1 -0
- package/build/types/manifest/base.d.ts +135 -0
- package/build/types/manifest/base.d.ts.map +1 -0
- package/build/types/manifest/base.js +3 -0
- package/build/types/manifest/base.js.map +1 -0
- package/build/types/manifest/index.d.ts +21 -0
- package/build/types/manifest/index.d.ts.map +1 -0
- package/build/types/manifest/index.js +42 -0
- package/build/types/manifest/index.js.map +1 -0
- package/build/types/manifest/v3.d.ts +139 -0
- package/build/types/manifest/v3.d.ts.map +1 -0
- package/build/types/manifest/v3.js +3 -0
- package/build/types/manifest/v3.js.map +1 -0
- package/build/types/manifest/v4.d.ts +139 -0
- package/build/types/manifest/v4.d.ts.map +1 -0
- package/build/types/manifest/v4.js +3 -0
- package/build/types/manifest/v4.js.map +1 -0
- package/driver.d.ts +1 -0
- package/driver.js +14 -0
- package/index.js +11 -0
- package/lib/appium.js +545 -188
- package/lib/cli/args.js +275 -407
- package/lib/cli/driver-command.js +132 -24
- package/lib/cli/extension-command.js +751 -272
- package/lib/cli/extension.js +38 -19
- package/lib/cli/parser.js +267 -95
- package/lib/cli/plugin-command.js +122 -22
- package/lib/cli/utils.js +24 -10
- package/lib/config-file.js +220 -0
- package/lib/config.js +243 -132
- package/lib/constants.js +79 -0
- package/lib/extension/driver-config.js +247 -0
- package/lib/extension/extension-config.js +709 -0
- package/lib/extension/index.js +116 -0
- package/lib/extension/manifest-migrations.js +136 -0
- package/lib/extension/manifest.js +580 -0
- package/lib/extension/package-changed.js +64 -0
- package/lib/extension/plugin-config.js +112 -0
- package/lib/grid-register.js +49 -35
- package/lib/logger.js +1 -2
- package/lib/logsink.js +59 -36
- package/lib/main.js +392 -104
- package/lib/schema/arg-spec.js +229 -0
- package/lib/schema/cli-args.js +241 -0
- package/lib/schema/cli-transformers.js +119 -0
- package/lib/schema/index.js +2 -0
- package/lib/schema/keywords.js +136 -0
- package/lib/schema/schema.js +725 -0
- package/lib/utils.js +310 -89
- package/package.json +84 -84
- package/plugin.d.ts +1 -0
- package/plugin.js +13 -0
- package/scripts/autoinstall-extensions.js +243 -0
- package/support.d.ts +1 -0
- package/support.js +13 -0
- package/tsconfig.json +25 -0
- package/types/cli.ts +193 -0
- package/types/index.ts +20 -0
- package/types/manifest/README.md +30 -0
- package/types/manifest/base.ts +158 -0
- package/types/manifest/index.ts +28 -0
- package/types/manifest/v3.ts +161 -0
- package/types/manifest/v4.ts +161 -0
- package/CHANGELOG.md +0 -3669
- package/bin/ios-webkit-debug-proxy-launcher.js +0 -71
- package/build/lib/cli/argparse-actions.js +0 -104
- package/build/lib/cli/npm.js +0 -207
- package/build/lib/cli/parser-helpers.js +0 -93
- package/build/lib/driver-config.js +0 -77
- package/build/lib/drivers.js +0 -99
- package/build/lib/extension-config.js +0 -253
- package/build/lib/plugin-config.js +0 -59
- package/build/lib/plugins.js +0 -16
- package/build/postinstall.js +0 -90
- package/lib/cli/argparse-actions.js +0 -77
- package/lib/cli/npm.js +0 -183
- package/lib/cli/parser-helpers.js +0 -91
- package/lib/driver-config.js +0 -46
- package/lib/drivers.js +0 -84
- package/lib/extension-config.js +0 -209
- package/lib/plugin-config.js +0 -34
- package/lib/plugins.js +0 -11
- package/postinstall.js +0 -71
package/lib/main.js
CHANGED
|
@@ -1,42 +1,65 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// transpile:main
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
import logger from './logger'; // logger needs to remain
|
|
3
|
+
import {init as logsinkInit} from './logsink'; // this import needs to come first since it sets up global npmlog
|
|
4
|
+
import logger from './logger'; // logger needs to remain second
|
|
5
|
+
import {routeConfiguringFunction as makeRouter, server as baseServer} from '@appium/base-driver';
|
|
6
|
+
import {logger as logFactory, util, env, fs} from '@appium/support';
|
|
7
|
+
import {asyncify} from 'asyncbox';
|
|
6
8
|
import _ from 'lodash';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { USE_ALL_PLUGINS } from './cli/args';
|
|
11
|
-
import { logger as logFactory, util } from 'appium-support';
|
|
9
|
+
import {AppiumDriver} from './appium';
|
|
10
|
+
import {runExtensionCommand} from './cli/extension';
|
|
11
|
+
import {getParser} from './cli/parser';
|
|
12
12
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
getGitRev,
|
|
13
|
+
APPIUM_VER,
|
|
14
|
+
checkNodeOk,
|
|
15
|
+
getGitRev,
|
|
16
|
+
getNonDefaultServerArgs,
|
|
17
|
+
showConfig,
|
|
18
|
+
showBuildInfo,
|
|
19
|
+
validateTmpDir,
|
|
20
|
+
warnNodeDeprecations,
|
|
21
|
+
checkNpmOk,
|
|
16
22
|
} from './config';
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import {
|
|
20
|
-
import { runExtensionCommand } from './cli/extension';
|
|
21
|
-
import { AppiumDriver } from './appium';
|
|
23
|
+
import {readConfigFile} from './config-file';
|
|
24
|
+
import {loadExtensions, getActivePlugins, getActiveDrivers} from './extension';
|
|
25
|
+
import {SERVER_SUBCOMMAND, LONG_STACKTRACE_LIMIT} from './constants';
|
|
22
26
|
import registerNode from './grid-register';
|
|
23
|
-
import {
|
|
27
|
+
import {getDefaultsForSchema, validate} from './schema/schema';
|
|
28
|
+
import {
|
|
29
|
+
inspect,
|
|
30
|
+
adjustNodePath,
|
|
31
|
+
isDriverCommandArgs,
|
|
32
|
+
isExtensionCommandArgs,
|
|
33
|
+
isPluginCommandArgs,
|
|
34
|
+
isServerCommandArgs,
|
|
35
|
+
fetchIpAddresses,
|
|
36
|
+
V4_BROADCAST_IP,
|
|
37
|
+
V6_BROADCAST_IP,
|
|
38
|
+
} from './utils';
|
|
39
|
+
import os from 'node:os';
|
|
24
40
|
|
|
41
|
+
const {resolveAppiumHome} = env;
|
|
25
42
|
|
|
26
|
-
|
|
43
|
+
/**
|
|
44
|
+
*
|
|
45
|
+
* @param {ParsedArgs} args
|
|
46
|
+
* @param {boolean} [throwInsteadOfExit]
|
|
47
|
+
*/
|
|
48
|
+
async function preflightChecks(args, throwInsteadOfExit = false) {
|
|
27
49
|
try {
|
|
28
50
|
checkNodeOk();
|
|
51
|
+
await checkNpmOk();
|
|
29
52
|
if (args.longStacktrace) {
|
|
30
|
-
|
|
53
|
+
Error.stackTraceLimit = LONG_STACKTRACE_LIMIT;
|
|
31
54
|
}
|
|
32
|
-
if (args.
|
|
33
|
-
await
|
|
55
|
+
if (args.showBuildInfo) {
|
|
56
|
+
await showBuildInfo();
|
|
34
57
|
process.exit(0);
|
|
35
58
|
}
|
|
36
59
|
warnNodeDeprecations();
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
60
|
+
|
|
61
|
+
validate(args);
|
|
62
|
+
|
|
40
63
|
if (args.tmpDir) {
|
|
41
64
|
await validateTmpDir(args.tmpDir);
|
|
42
65
|
}
|
|
@@ -50,18 +73,29 @@ async function preflightChecks ({parser, args, driverConfig, pluginConfig, throw
|
|
|
50
73
|
}
|
|
51
74
|
}
|
|
52
75
|
|
|
53
|
-
|
|
76
|
+
/**
|
|
77
|
+
* @param {Args} args
|
|
78
|
+
*/
|
|
79
|
+
function logNonDefaultArgsWarning(args) {
|
|
54
80
|
logger.info('Non-default server args:');
|
|
55
|
-
|
|
81
|
+
inspect(args);
|
|
56
82
|
}
|
|
57
83
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
84
|
+
/**
|
|
85
|
+
* @param {Args['defaultCapabilities']} caps
|
|
86
|
+
*/
|
|
87
|
+
function logDefaultCapabilitiesWarning(caps) {
|
|
88
|
+
logger.info(
|
|
89
|
+
'Default capabilities, which will be added to each request ' +
|
|
90
|
+
'unless overridden by desired capabilities:'
|
|
91
|
+
);
|
|
92
|
+
inspect(caps);
|
|
62
93
|
}
|
|
63
94
|
|
|
64
|
-
|
|
95
|
+
/**
|
|
96
|
+
* @param {ParsedArgs} args
|
|
97
|
+
*/
|
|
98
|
+
async function logStartupInfo(args) {
|
|
65
99
|
let welcome = `Welcome to Appium v${APPIUM_VER}`;
|
|
66
100
|
let appiumRev = await getGitRev();
|
|
67
101
|
if (appiumRev) {
|
|
@@ -69,7 +103,7 @@ async function logStartupInfo (parser, args) {
|
|
|
69
103
|
}
|
|
70
104
|
logger.info(welcome);
|
|
71
105
|
|
|
72
|
-
let showArgs =
|
|
106
|
+
let showArgs = getNonDefaultServerArgs(args);
|
|
73
107
|
if (_.size(showArgs)) {
|
|
74
108
|
logNonDefaultArgsWarning(showArgs);
|
|
75
109
|
}
|
|
@@ -83,20 +117,114 @@ async function logStartupInfo (parser, args) {
|
|
|
83
117
|
// }
|
|
84
118
|
}
|
|
85
119
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Gets a list of `updateServer` functions from all extensions
|
|
122
|
+
* @param {DriverNameMap} driverClasses
|
|
123
|
+
* @param {PluginNameMap} pluginClasses
|
|
124
|
+
* @returns {import('@appium/types').UpdateServerCallback[]}
|
|
125
|
+
*/
|
|
126
|
+
function getServerUpdaters(driverClasses, pluginClasses) {
|
|
127
|
+
return _.compact(_.map([...driverClasses.keys(), ...pluginClasses.keys()], 'updateServer'));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Makes a big `MethodMap` from all the little `MethodMap`s in the extensions
|
|
132
|
+
* @param {DriverNameMap} driverClasses
|
|
133
|
+
* @param {PluginNameMap} pluginClasses
|
|
134
|
+
* @returns {import('@appium/types').MethodMap<import('@appium/types').Driver>}
|
|
135
|
+
*/
|
|
136
|
+
function getExtraMethodMap(driverClasses, pluginClasses) {
|
|
137
|
+
return [...driverClasses.keys(), ...pluginClasses.keys()].reduce(
|
|
138
|
+
(map, klass) => ({
|
|
139
|
+
...map,
|
|
140
|
+
...(klass.newMethodMap ?? {}),
|
|
141
|
+
}),
|
|
142
|
+
{}
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Prepares and validates appium home path folder
|
|
148
|
+
*
|
|
149
|
+
* @param {string} name The name of the appium home source (needed for error messages)
|
|
150
|
+
* @param {string} appiumHome The actual value to be verified
|
|
151
|
+
* @returns {Promise<string>} Same appiumHome value
|
|
152
|
+
* @throws {Error} If the validation has failed
|
|
153
|
+
*/
|
|
154
|
+
async function prepareAppiumHome(name, appiumHome) {
|
|
155
|
+
let stat;
|
|
156
|
+
try {
|
|
157
|
+
stat = await fs.stat(appiumHome);
|
|
158
|
+
} catch (e) {
|
|
159
|
+
let err = e;
|
|
160
|
+
if (e.code === 'ENOENT') {
|
|
161
|
+
try {
|
|
162
|
+
await fs.mkdir(appiumHome, {recursive: true});
|
|
163
|
+
return appiumHome;
|
|
164
|
+
} catch (e1) {
|
|
165
|
+
err = e1;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
throw new Error(
|
|
169
|
+
`The path '${appiumHome}' provided in the ${name} must point ` +
|
|
170
|
+
`to a valid folder writeable for the current user account '${os.userInfo().username}'. ` +
|
|
171
|
+
`Original error: ${err.message}`
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
if (!stat.isDirectory()) {
|
|
175
|
+
throw new Error(
|
|
176
|
+
`The path '${appiumHome}' provided in the ${name} must point to a valid folder`
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
await fs.access(appiumHome, fs.constants.W_OK);
|
|
181
|
+
} catch (e) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`The folder path '${appiumHome}' provided in the ${name} must be ` +
|
|
184
|
+
`writeable for the current user account '${os.userInfo().username}. ` +
|
|
185
|
+
`Original error: ${e.message}`
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return appiumHome;
|
|
90
189
|
}
|
|
91
190
|
|
|
92
|
-
|
|
93
|
-
|
|
191
|
+
/**
|
|
192
|
+
* Initializes Appium, but does not start the server.
|
|
193
|
+
*
|
|
194
|
+
* Use this to get at the configuration schema.
|
|
195
|
+
*
|
|
196
|
+
* If `args` contains a non-empty `subcommand` which is not `server`, this function will return an empty object.
|
|
197
|
+
*
|
|
198
|
+
* @template {CliCommand} [Cmd=ServerCommand]
|
|
199
|
+
* @template {CliExtensionSubcommand|void} [SubCmd=void]
|
|
200
|
+
* @param {Args<Cmd, SubCmd>} [args] - Partial args (progammatic usage only)
|
|
201
|
+
* @returns {Promise<InitResult<Cmd>>}
|
|
202
|
+
* @example
|
|
203
|
+
* import {init, getSchema} from 'appium';
|
|
204
|
+
* const options = {}; // config object
|
|
205
|
+
* await init(options);
|
|
206
|
+
* const schema = getSchema(); // entire config schema including plugins and drivers
|
|
207
|
+
*/
|
|
208
|
+
async function init(args) {
|
|
209
|
+
const appiumHome = args?.appiumHome ?? (await resolveAppiumHome());
|
|
210
|
+
let appiumHomeSourceName = 'autodetected appium home path';
|
|
211
|
+
if (!_.isNil(args?.appiumHome)) {
|
|
212
|
+
appiumHomeSourceName = 'appiumHome config value';
|
|
213
|
+
} else if (process.env.APPIUM_HOME) {
|
|
214
|
+
appiumHomeSourceName = 'APPIUM_HOME environment variable';
|
|
215
|
+
}
|
|
216
|
+
await prepareAppiumHome(appiumHomeSourceName, appiumHome);
|
|
217
|
+
|
|
218
|
+
adjustNodePath();
|
|
219
|
+
|
|
220
|
+
const {driverConfig, pluginConfig} = await loadExtensions(appiumHome);
|
|
221
|
+
|
|
222
|
+
const parser = getParser();
|
|
94
223
|
let throwInsteadOfExit = false;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// with defaults
|
|
98
|
-
args = Object.assign({}, getDefaultServerArgs(), args);
|
|
224
|
+
/** @type {Args<Cmd, SubCmd>} */
|
|
225
|
+
let preConfigArgs;
|
|
99
226
|
|
|
227
|
+
if (args) {
|
|
100
228
|
// if we have a containing package instead of running as a CLI process,
|
|
101
229
|
// that package might not appreciate us calling 'process.exit' willy-
|
|
102
230
|
// nilly, so give it the option to have us throw instead of exit
|
|
@@ -105,84 +233,192 @@ async function main (args = null) {
|
|
|
105
233
|
// but remove it since it's not a real server arg per se
|
|
106
234
|
delete args.throwInsteadOfExit;
|
|
107
235
|
}
|
|
236
|
+
preConfigArgs = {...args, subcommand: args.subcommand ?? SERVER_SUBCOMMAND};
|
|
108
237
|
} else {
|
|
109
238
|
// otherwise parse from CLI
|
|
110
|
-
|
|
239
|
+
preConfigArgs = /** @type {Args<Cmd, SubCmd>} */ (parser.parseArgs());
|
|
111
240
|
}
|
|
112
|
-
await logsinkInit(args);
|
|
113
241
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
242
|
+
const configResult = await readConfigFile(preConfigArgs.configFile);
|
|
243
|
+
|
|
244
|
+
if (!_.isEmpty(configResult.errors)) {
|
|
245
|
+
throw new Error(
|
|
246
|
+
`Errors in config file ${configResult.filepath}:\n ${
|
|
247
|
+
configResult.reason ?? configResult.errors
|
|
248
|
+
}`
|
|
249
|
+
);
|
|
119
250
|
}
|
|
120
251
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
252
|
+
// merge config and apply defaults.
|
|
253
|
+
// the order of precendece is:
|
|
254
|
+
// 1. command line args
|
|
255
|
+
// 2. config file
|
|
256
|
+
// 3. defaults from config file.
|
|
257
|
+
if (isServerCommandArgs(preConfigArgs)) {
|
|
258
|
+
const defaults = getDefaultsForSchema(false);
|
|
259
|
+
|
|
260
|
+
/** @type {ParsedArgs} */
|
|
261
|
+
const serverArgs = _.defaultsDeep({}, preConfigArgs, configResult.config?.server, defaults);
|
|
262
|
+
|
|
263
|
+
if (preConfigArgs.showConfig) {
|
|
264
|
+
showConfig(getNonDefaultServerArgs(preConfigArgs), configResult, defaults, serverArgs);
|
|
265
|
+
return /** @type {InitResult<Cmd>} */ ({});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
await logsinkInit(serverArgs);
|
|
269
|
+
|
|
270
|
+
if (serverArgs.logFilters) {
|
|
271
|
+
const {issues, rules} = await logFactory.loadSecureValuesPreprocessingRules(
|
|
272
|
+
serverArgs.logFilters
|
|
273
|
+
);
|
|
274
|
+
if (!_.isEmpty(issues)) {
|
|
275
|
+
throw new Error(
|
|
276
|
+
`The log filtering rules config '${serverArgs.logFilters}' has issues: ` +
|
|
277
|
+
JSON.stringify(issues, null, 2)
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
if (_.isEmpty(rules)) {
|
|
281
|
+
logger.warn(
|
|
282
|
+
`Found no log filtering rules in '${serverArgs.logFilters}'. Is that expected?`
|
|
283
|
+
);
|
|
284
|
+
} else {
|
|
285
|
+
logger.info(
|
|
286
|
+
`Loaded ${util.pluralize('filtering rule', rules.length, true)} from '${
|
|
287
|
+
serverArgs.logFilters
|
|
288
|
+
}'`
|
|
289
|
+
);
|
|
290
|
+
}
|
|
126
291
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
292
|
+
|
|
293
|
+
const appiumDriver = new AppiumDriver(
|
|
294
|
+
/** @type {import('@appium/types').DriverOpts<import('./appium').AppiumDriverConstraints>} */ (
|
|
295
|
+
serverArgs
|
|
296
|
+
)
|
|
297
|
+
);
|
|
298
|
+
// set the config on the umbrella driver so it can match drivers to caps
|
|
299
|
+
appiumDriver.driverConfig = driverConfig;
|
|
300
|
+
await preflightChecks(serverArgs, throwInsteadOfExit);
|
|
301
|
+
|
|
302
|
+
return /** @type {InitResult<Cmd>} */ ({
|
|
303
|
+
appiumDriver,
|
|
304
|
+
parsedArgs: serverArgs,
|
|
305
|
+
driverConfig,
|
|
306
|
+
pluginConfig,
|
|
307
|
+
});
|
|
308
|
+
} else {
|
|
309
|
+
if (isExtensionCommandArgs(preConfigArgs)) {
|
|
310
|
+
// if the user has requested the 'driver' CLI, don't run the normal server,
|
|
311
|
+
// but instead pass control to the driver CLI
|
|
312
|
+
if (isDriverCommandArgs(preConfigArgs)) {
|
|
313
|
+
await runExtensionCommand(preConfigArgs, driverConfig);
|
|
314
|
+
}
|
|
315
|
+
if (isPluginCommandArgs(preConfigArgs)) {
|
|
316
|
+
await runExtensionCommand(preConfigArgs, pluginConfig);
|
|
317
|
+
}
|
|
131
318
|
}
|
|
319
|
+
return /** @type {InitResult<Cmd>} */ ({});
|
|
132
320
|
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Prints the actual server address and the list of URLs that
|
|
325
|
+
* could be used to connect to the current server.
|
|
326
|
+
* Properly replaces broadcast addresses in client URLs.
|
|
327
|
+
*
|
|
328
|
+
* @param {string} url The URL the server is listening on
|
|
329
|
+
*/
|
|
330
|
+
function logServerAddress(url) {
|
|
331
|
+
logger.info(`Appium REST http interface listener started on ${url}`);
|
|
332
|
+
const urlObj = new URL(url);
|
|
333
|
+
if (![V4_BROADCAST_IP, V6_BROADCAST_IP].includes(urlObj.hostname)) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const ips = fetchIpAddresses(urlObj.hostname === V4_BROADCAST_IP ? 4 : 6);
|
|
338
|
+
logger.info(
|
|
339
|
+
`You can provide the following ${util.pluralize('URL', ips.length, false)} ` +
|
|
340
|
+
`in your client code to connect to this server:\n` +
|
|
341
|
+
ips.map((x) => `\t${urlObj.href.replace(urlObj.hostname, x)}`).join('\n')
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Initializes Appium's config. Starts server if appropriate and resolves the
|
|
347
|
+
* server instance if so; otherwise resolves w/ `undefined`.
|
|
348
|
+
* @template {CliCommand} [Cmd=ServerCommand]
|
|
349
|
+
* @template {CliExtensionSubcommand|void} [SubCmd=void]
|
|
350
|
+
* @param {Args<Cmd, SubCmd>} [args] - Arguments from CLI or otherwise
|
|
351
|
+
* @returns {Promise<Cmd extends ServerCommand ? import('@appium/types').AppiumServer : void>}
|
|
352
|
+
*/
|
|
353
|
+
async function main(args) {
|
|
354
|
+
const initResult = await init(args);
|
|
355
|
+
|
|
356
|
+
if (_.isEmpty(initResult)) {
|
|
357
|
+
// if this branch is taken, we've run a different subcommand, so there's nothing
|
|
358
|
+
// left to do here.
|
|
359
|
+
return /** @type {Cmd extends ServerCommand ? import('@appium/types').AppiumServer : void} */ (
|
|
360
|
+
undefined
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const {appiumDriver, pluginConfig, driverConfig, parsedArgs} =
|
|
365
|
+
/** @type {InitResult<ServerCommand>} */ (initResult);
|
|
133
366
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
await
|
|
139
|
-
await logStartupInfo(parser, args);
|
|
367
|
+
const pluginClasses = getActivePlugins(pluginConfig, parsedArgs.usePlugins);
|
|
368
|
+
// set the active plugins on the umbrella driver so it can use them for commands
|
|
369
|
+
appiumDriver.pluginClasses = pluginClasses;
|
|
370
|
+
|
|
371
|
+
await logStartupInfo(parsedArgs);
|
|
140
372
|
let routeConfiguringFunction = makeRouter(appiumDriver);
|
|
141
373
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
// it can use them to wrap command execution
|
|
146
|
-
const plugins = Object.keys(pluginConfig.installedExtensions).filter((pluginName) =>
|
|
147
|
-
_.includes(args.plugins, pluginName) ||
|
|
148
|
-
(args.plugins.length === 1 && args.plugins[0] === USE_ALL_PLUGINS)
|
|
149
|
-
).map((pluginName) => {
|
|
150
|
-
try {
|
|
151
|
-
const PluginClass = pluginConfig.require(pluginName);
|
|
152
|
-
return new PluginClass(pluginName);
|
|
153
|
-
} catch (err) {
|
|
154
|
-
logger.error(`Could not load plugin '${pluginName}', so it will not be available. Error ` +
|
|
155
|
-
`in loading the plugin was: ${err}`);
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
}).filter(Boolean);
|
|
159
|
-
appiumDriver.plugins = plugins;
|
|
374
|
+
const driverClasses = getActiveDrivers(driverConfig, parsedArgs.useDrivers);
|
|
375
|
+
const serverUpdaters = getServerUpdaters(driverClasses, pluginClasses);
|
|
376
|
+
const extraMethodMap = getExtraMethodMap(driverClasses, pluginClasses);
|
|
160
377
|
|
|
378
|
+
/** @type {import('@appium/base-driver').ServerOpts} */
|
|
161
379
|
const serverOpts = {
|
|
162
380
|
routeConfiguringFunction,
|
|
163
|
-
port:
|
|
164
|
-
hostname:
|
|
165
|
-
allowCors:
|
|
166
|
-
basePath:
|
|
167
|
-
|
|
381
|
+
port: parsedArgs.port,
|
|
382
|
+
hostname: parsedArgs.address,
|
|
383
|
+
allowCors: parsedArgs.allowCors,
|
|
384
|
+
basePath: parsedArgs.basePath,
|
|
385
|
+
serverUpdaters,
|
|
386
|
+
extraMethodMap,
|
|
387
|
+
cliArgs: parsedArgs,
|
|
168
388
|
};
|
|
169
|
-
if (
|
|
170
|
-
serverOpts.keepAliveTimeout =
|
|
389
|
+
if (parsedArgs.keepAliveTimeout) {
|
|
390
|
+
serverOpts.keepAliveTimeout = parsedArgs.keepAliveTimeout * 1000;
|
|
171
391
|
}
|
|
172
|
-
let server
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
392
|
+
let server;
|
|
393
|
+
try {
|
|
394
|
+
server = await baseServer(serverOpts);
|
|
395
|
+
} catch (err) {
|
|
396
|
+
logger.error(
|
|
397
|
+
`Could not configure Appium server. It's possible that a driver or plugin tried ` +
|
|
398
|
+
`to update the server and failed. Original error: ${err.message}`
|
|
399
|
+
);
|
|
400
|
+
logger.debug(err.stack);
|
|
401
|
+
return process.exit(1);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (parsedArgs.allowCors) {
|
|
405
|
+
logger.warn(
|
|
406
|
+
'You have enabled CORS requests from any host. Be careful not ' +
|
|
407
|
+
'to visit sites which could maliciously try to start Appium ' +
|
|
408
|
+
'sessions on your machine'
|
|
409
|
+
);
|
|
177
410
|
}
|
|
178
411
|
appiumDriver.server = server;
|
|
179
412
|
try {
|
|
180
|
-
// TODO prelaunch if args.launch is set
|
|
181
|
-
// TODO: startAlertSocket(server, appiumServer);
|
|
182
|
-
|
|
183
413
|
// configure as node on grid, if necessary
|
|
184
|
-
|
|
185
|
-
|
|
414
|
+
// falsy values should not cause this to run
|
|
415
|
+
if (parsedArgs.nodeconfig) {
|
|
416
|
+
await registerNode(
|
|
417
|
+
parsedArgs.nodeconfig,
|
|
418
|
+
parsedArgs.address,
|
|
419
|
+
parsedArgs.port,
|
|
420
|
+
parsedArgs.basePath
|
|
421
|
+
);
|
|
186
422
|
}
|
|
187
423
|
} catch (err) {
|
|
188
424
|
await server.close();
|
|
@@ -190,7 +426,7 @@ async function main (args = null) {
|
|
|
190
426
|
}
|
|
191
427
|
|
|
192
428
|
for (const signal of ['SIGINT', 'SIGTERM']) {
|
|
193
|
-
process.once(signal, async function onSignal
|
|
429
|
+
process.once(signal, async function onSignal() {
|
|
194
430
|
logger.info(`Received ${signal} - shutting down`);
|
|
195
431
|
try {
|
|
196
432
|
await appiumDriver.deleteAllSessions({
|
|
@@ -206,15 +442,67 @@ async function main (args = null) {
|
|
|
206
442
|
});
|
|
207
443
|
}
|
|
208
444
|
|
|
209
|
-
|
|
445
|
+
logServerAddress(`http://${parsedArgs.address}:${parsedArgs.port}${parsedArgs.basePath}`);
|
|
446
|
+
|
|
210
447
|
driverConfig.print();
|
|
211
|
-
pluginConfig.print(
|
|
448
|
+
pluginConfig.print([...pluginClasses.values()]);
|
|
212
449
|
|
|
213
|
-
return
|
|
450
|
+
return /** @type {Cmd extends ServerCommand ? import('@appium/types').AppiumServer : void} */ (
|
|
451
|
+
server
|
|
452
|
+
);
|
|
214
453
|
}
|
|
215
454
|
|
|
455
|
+
// NOTE: this is here for backwards compat for any scripts referencing `main.js` directly
|
|
456
|
+
// (more specifically, `build/lib/main.js`)
|
|
457
|
+
// the executable is now `../index.js`, so that module will typically be `require.main`.
|
|
216
458
|
if (require.main === module) {
|
|
217
459
|
asyncify(main);
|
|
218
460
|
}
|
|
219
461
|
|
|
220
|
-
|
|
462
|
+
// everything below here is intended to be a public API.
|
|
463
|
+
export {readConfigFile} from './config-file';
|
|
464
|
+
export {finalizeSchema, getSchema, validate} from './schema/schema';
|
|
465
|
+
export {main, init, resolveAppiumHome};
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* @typedef {import('@appium/types').DriverType} DriverType
|
|
469
|
+
* @typedef {import('@appium/types').PluginType} PluginType
|
|
470
|
+
* @typedef {import('@appium/types').DriverClass} DriverClass
|
|
471
|
+
* @typedef {import('@appium/types').PluginClass} PluginClass
|
|
472
|
+
* @typedef {import('appium/types').CliCommand} CliCommand
|
|
473
|
+
* @typedef {import('appium/types').CliExtensionSubcommand} CliExtensionSubcommand
|
|
474
|
+
* @typedef {import('appium/types').CliExtensionCommand} CliExtensionCommand
|
|
475
|
+
* @typedef {import('appium/types').CliCommandServer} ServerCommand
|
|
476
|
+
* @typedef {import('appium/types').CliCommandDriver} DriverCommand
|
|
477
|
+
* @typedef {import('appium/types').CliCommandPlugin} PluginCommand
|
|
478
|
+
* @typedef {import('./extension').DriverNameMap} DriverNameMap
|
|
479
|
+
* @typedef {import('./extension').PluginNameMap} PluginNameMap
|
|
480
|
+
*/
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Literally an empty object
|
|
484
|
+
* @typedef { {} } ExtCommandInitResult
|
|
485
|
+
*/
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* @typedef ServerInitData
|
|
489
|
+
* @property {import('./appium').AppiumDriver} appiumDriver - The Appium driver
|
|
490
|
+
* @property {import('appium/types').ParsedArgs} parsedArgs - The parsed arguments
|
|
491
|
+
*/
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* @template {CliCommand} Cmd
|
|
495
|
+
* @typedef {Cmd extends ServerCommand ? ServerInitData & import('./extension').ExtensionConfigs : ExtCommandInitResult} InitResult
|
|
496
|
+
*/
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* @template {CliCommand} [Cmd=ServerCommand]
|
|
500
|
+
* @template {CliExtensionSubcommand|void} [SubCmd=void]
|
|
501
|
+
* @typedef {import('appium/types').Args<Cmd, SubCmd>} Args
|
|
502
|
+
*/
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* @template {CliCommand} [Cmd=ServerCommand]
|
|
506
|
+
* @template {CliExtensionSubcommand|void} [SubCmd=void]
|
|
507
|
+
* @typedef {import('appium/types').ParsedArgs<Cmd, SubCmd>} ParsedArgs
|
|
508
|
+
*/
|