appium 3.2.2 → 3.3.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/cli/args.d.ts +16 -12
- package/build/lib/cli/args.d.ts.map +1 -1
- package/build/lib/cli/args.js +15 -35
- 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 +211 -415
- package/build/lib/cli/extension-command.d.ts.map +1 -1
- package/build/lib/cli/extension-command.js +384 -653
- package/build/lib/cli/extension-command.js.map +1 -1
- package/build/lib/cli/extension.d.ts +11 -16
- package/build/lib/cli/extension.d.ts.map +1 -1
- package/build/lib/cli/extension.js +10 -28
- package/build/lib/cli/extension.js.map +1 -1
- package/build/lib/cli/parser.d.ts +40 -69
- package/build/lib/cli/parser.d.ts.map +1 -1
- package/build/lib/cli/parser.js +24 -59
- 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 +13 -55
- package/build/lib/cli/setup-command.js.map +1 -1
- package/build/lib/cli/utils.d.ts +27 -29
- package/build/lib/cli/utils.d.ts.map +1 -1
- package/build/lib/cli/utils.js +29 -31
- package/build/lib/cli/utils.js.map +1 -1
- package/build/lib/config-file.d.ts +24 -67
- package/build/lib/config-file.d.ts.map +1 -1
- package/build/lib/config-file.js +56 -115
- package/build/lib/config-file.js.map +1 -1
- package/build/lib/config.d.ts +42 -44
- package/build/lib/config.d.ts.map +1 -1
- package/build/lib/config.js +75 -107
- package/build/lib/config.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 +29 -60
- package/build/lib/doctor/doctor.js.map +1 -1
- package/build/lib/grid-register.d.ts +32 -7
- package/build/lib/grid-register.d.ts.map +1 -1
- package/build/lib/grid-register.js +84 -48
- package/build/lib/grid-register.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.js +1 -1
- 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.d.ts +3 -15
- package/build/lib/schema/cli-args.d.ts.map +1 -1
- package/build/lib/schema/cli-args.js +15 -105
- 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/index.d.ts +2 -2
- package/build/lib/schema/index.d.ts.map +1 -1
- 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 +75 -345
- package/build/lib/schema/schema.js.map +1 -1
- package/build/lib/utils.d.ts +59 -238
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +55 -207
- package/build/lib/utils.js.map +1 -1
- package/lib/cli/{args.js → args.ts} +40 -51
- package/lib/cli/driver-command.ts +122 -0
- package/lib/cli/{extension-command.js → extension-command.ts} +610 -689
- package/lib/cli/extension.ts +65 -0
- package/lib/cli/{parser.js → parser.ts} +48 -71
- package/lib/cli/plugin-command.ts +117 -0
- package/lib/cli/{setup-command.js → setup-command.ts} +57 -72
- package/lib/cli/utils.ts +97 -0
- package/lib/config-file.ts +212 -0
- package/lib/{config.js → config.ts} +129 -141
- package/lib/{constants.js → constants.ts} +30 -41
- package/lib/doctor/{doctor.js → doctor.ts} +81 -91
- package/lib/grid-register.ts +250 -0
- package/lib/{logsink.js → logsink.ts} +91 -137
- package/lib/main.js +1 -1
- package/lib/schema/arg-spec.ts +131 -0
- package/lib/schema/cli-args.ts +171 -0
- package/lib/schema/cli-transformers.ts +83 -0
- package/lib/schema/keywords.ts +96 -0
- package/lib/schema/schema.ts +449 -0
- package/lib/utils.ts +404 -0
- package/package.json +16 -16
- 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/grid-register.js +0 -146
- 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/keywords.js +0 -136
- package/lib/schema/schema.js +0 -725
- package/lib/utils.js +0 -512
- /package/lib/schema/{index.js → index.ts} +0 -0
|
@@ -8,31 +8,25 @@ import os from 'node:os';
|
|
|
8
8
|
import {npmPackage} from './utils';
|
|
9
9
|
import B from 'bluebird';
|
|
10
10
|
import {getDefaultsForSchema, getAllArgSpecs} from './schema/schema';
|
|
11
|
+
import type {BuildInfo, Args} from 'appium/types';
|
|
12
|
+
import type {ReadConfigFileResult} from './config-file';
|
|
11
13
|
|
|
12
14
|
export const APPIUM_VER = npmPackage.version;
|
|
13
|
-
const ENGINES =
|
|
15
|
+
const ENGINES = npmPackage.engines as Record<string, string>;
|
|
14
16
|
const MIN_NODE_VERSION = ENGINES.node;
|
|
15
17
|
export const rootDir = fs.findRoot(__dirname);
|
|
16
18
|
|
|
17
19
|
const GIT_BINARY = `git${system.isWindows() ? '.exe' : ''}`;
|
|
18
20
|
const GITHUB_API = 'https://api.github.com/repos/appium/appium';
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
* @type {import('appium/types').BuildInfo}
|
|
22
|
-
*/
|
|
23
|
-
const BUILD_INFO = {
|
|
22
|
+
const BUILD_INFO: BuildInfo = {
|
|
24
23
|
version: APPIUM_VER,
|
|
25
24
|
};
|
|
26
25
|
|
|
27
|
-
function getNodeVersion() {
|
|
28
|
-
return /** @type {import('semver').SemVer} */ (semver.coerce(process.version));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
26
|
/**
|
|
32
|
-
*
|
|
33
|
-
* @returns {Promise<void>}
|
|
27
|
+
* Update mutable build info metadata from local git or GitHub fallback.
|
|
34
28
|
*/
|
|
35
|
-
export async function updateBuildInfo(useGithubApiFallback = false) {
|
|
29
|
+
export async function updateBuildInfo(useGithubApiFallback = false): Promise<void> {
|
|
36
30
|
const sha = await getGitRev(useGithubApiFallback);
|
|
37
31
|
if (!sha) {
|
|
38
32
|
return;
|
|
@@ -44,35 +38,22 @@ export async function updateBuildInfo(useGithubApiFallback = false) {
|
|
|
44
38
|
}
|
|
45
39
|
}
|
|
46
40
|
|
|
47
|
-
/** @type {() => Promise<string?>} */
|
|
48
|
-
const getFullGitPath = _.memoize(async function getFullGitPath() {
|
|
49
|
-
try {
|
|
50
|
-
return await fs.which(GIT_BINARY);
|
|
51
|
-
} catch {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
41
|
/**
|
|
57
|
-
* Prints server debug
|
|
58
|
-
*
|
|
59
|
-
* @param {{
|
|
60
|
-
* driverConfig: import('./extension/driver-config').DriverConfig,
|
|
61
|
-
* pluginConfig: import('./extension/plugin-config').PluginConfig,
|
|
62
|
-
* appiumHome: string
|
|
63
|
-
* }} info
|
|
64
|
-
* @returns {Promise<void>}
|
|
42
|
+
* Prints server debug info to stdout.
|
|
65
43
|
*/
|
|
66
|
-
export async function showDebugInfo({driverConfig, pluginConfig, appiumHome}) {
|
|
67
|
-
const getNpmVersion = async () => {
|
|
44
|
+
export async function showDebugInfo({driverConfig, pluginConfig, appiumHome}: DebugInfoInput): Promise<void> {
|
|
45
|
+
const getNpmVersion = async (): Promise<string> => {
|
|
68
46
|
const {stdout} = await npm.exec('--version', [], {cwd: process.cwd()});
|
|
69
47
|
return _.trim(stdout);
|
|
70
48
|
};
|
|
71
|
-
const findNpmLocation = async () =>
|
|
49
|
+
const findNpmLocation = async (): Promise<string> =>
|
|
50
|
+
await fs.which(system.isWindows() ? 'npm.cmd' : 'npm');
|
|
51
|
+
|
|
72
52
|
const [npmVersion, npmLocation] = await B.all([
|
|
73
|
-
...
|
|
74
|
-
|
|
53
|
+
...[getNpmVersion, findNpmLocation].map((f) => getSafeResult(f, 'unknown')),
|
|
54
|
+
updateBuildInfo() as Promise<unknown>,
|
|
75
55
|
]);
|
|
56
|
+
|
|
76
57
|
const debugInfo = {
|
|
77
58
|
os: {
|
|
78
59
|
platform: os.platform(),
|
|
@@ -104,10 +85,12 @@ export async function showDebugInfo({driverConfig, pluginConfig, appiumHome}) {
|
|
|
104
85
|
}
|
|
105
86
|
|
|
106
87
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
88
|
+
* Returns the current git commit SHA for this Appium checkout.
|
|
89
|
+
*
|
|
90
|
+
* Attempts to read from local git first; when unavailable and fallback is enabled,
|
|
91
|
+
* queries the GitHub API for the tag matching the current Appium version.
|
|
109
92
|
*/
|
|
110
|
-
export async function getGitRev(useGithubApiFallback = false) {
|
|
93
|
+
export async function getGitRev(useGithubApiFallback = false): Promise<string | null> {
|
|
111
94
|
const fullGitPath = await getFullGitPath();
|
|
112
95
|
if (fullGitPath) {
|
|
113
96
|
try {
|
|
@@ -136,90 +119,56 @@ export async function getGitRev(useGithubApiFallback = false) {
|
|
|
136
119
|
return null;
|
|
137
120
|
}
|
|
138
121
|
|
|
139
|
-
/**
|
|
140
|
-
* @param {string} commitSha
|
|
141
|
-
* @param {boolean} [useGithubApiFallback]
|
|
142
|
-
* @returns {Promise<string?>}
|
|
143
|
-
*/
|
|
144
|
-
async function getGitTimestamp(commitSha, useGithubApiFallback = false) {
|
|
145
|
-
const fullGitPath = await getFullGitPath();
|
|
146
|
-
if (fullGitPath) {
|
|
147
|
-
try {
|
|
148
|
-
const {stdout} = await exec(fullGitPath, ['show', '-s', '--format=%ci', commitSha], {
|
|
149
|
-
cwd: __dirname,
|
|
150
|
-
});
|
|
151
|
-
return stdout.trim();
|
|
152
|
-
} catch {}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (!useGithubApiFallback) {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
try {
|
|
160
|
-
return (
|
|
161
|
-
await axios.get(`${GITHUB_API}/git/tags/${commitSha}`, {
|
|
162
|
-
headers: {
|
|
163
|
-
'User-Agent': `Appium ${APPIUM_VER}`,
|
|
164
|
-
},
|
|
165
|
-
})
|
|
166
|
-
).data?.tagger?.date;
|
|
167
|
-
} catch {}
|
|
168
|
-
return null;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
122
|
/**
|
|
172
123
|
* Mutable object containing Appium build information. By default it
|
|
173
124
|
* only contains the Appium version, but is updated with the build timestamp
|
|
174
125
|
* and git commit hash asynchronously as soon as `updateBuildInfo` is called
|
|
175
126
|
* and succeeds.
|
|
176
|
-
* @returns {import('appium/types').BuildInfo}
|
|
177
127
|
*/
|
|
178
|
-
export function getBuildInfo() {
|
|
128
|
+
export function getBuildInfo(): BuildInfo {
|
|
179
129
|
return BUILD_INFO;
|
|
180
130
|
}
|
|
181
131
|
|
|
182
132
|
/**
|
|
183
|
-
* @returns {void}
|
|
184
133
|
* @throws {Error} If Node version is outside of the supported range
|
|
185
134
|
*/
|
|
186
|
-
export function checkNodeOk() {
|
|
135
|
+
export function checkNodeOk(): void {
|
|
187
136
|
const version = getNodeVersion();
|
|
188
137
|
if (!semver.satisfies(version, MIN_NODE_VERSION)) {
|
|
189
|
-
throw new Error(
|
|
190
|
-
`Node version must be at least ${MIN_NODE_VERSION}; current is ${version.version}`
|
|
191
|
-
);
|
|
138
|
+
throw new Error(`Node version must be at least ${MIN_NODE_VERSION}; current is ${version.version}`);
|
|
192
139
|
}
|
|
193
140
|
}
|
|
194
141
|
|
|
195
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Prints the current build info JSON to stdout.
|
|
144
|
+
*
|
|
145
|
+
* This updates build metadata first (using GitHub fallback) and then logs the
|
|
146
|
+
* resulting {@link BuildInfo} object.
|
|
147
|
+
*/
|
|
148
|
+
export async function showBuildInfo(): Promise<void> {
|
|
196
149
|
await updateBuildInfo(true);
|
|
197
150
|
console.log(JSON.stringify(getBuildInfo()));
|
|
198
151
|
}
|
|
199
152
|
|
|
200
153
|
/**
|
|
201
154
|
* Returns k/v pairs of server arguments which are _not_ the defaults.
|
|
202
|
-
* @param {Args} parsedArgs
|
|
203
|
-
* @returns {Args}
|
|
204
155
|
*/
|
|
205
|
-
export function getNonDefaultServerArgs(parsedArgs) {
|
|
156
|
+
export function getNonDefaultServerArgs(parsedArgs: Args): Args {
|
|
206
157
|
/**
|
|
207
158
|
* Flattens parsed args into a single level object for comparison with
|
|
208
159
|
* flattened defaults across server args and extension args.
|
|
209
|
-
* @param {Args} args
|
|
210
|
-
* @returns {Record<string, { value: any, argSpec: ArgSpec }>}
|
|
211
160
|
*/
|
|
212
|
-
const flatten = (args) => {
|
|
161
|
+
const flatten = (args: Args): Record<string, FlattenedArg> => {
|
|
213
162
|
const argSpecs = getAllArgSpecs();
|
|
214
163
|
const flattened = _.reduce(
|
|
215
164
|
[...argSpecs.values()],
|
|
216
|
-
(acc, argSpec) => {
|
|
165
|
+
(acc: Record<string, FlattenedArg>, argSpec: {dest: string}) => {
|
|
217
166
|
if (_.has(args, argSpec.dest)) {
|
|
218
167
|
acc[argSpec.dest] = {value: _.get(args, argSpec.dest), argSpec};
|
|
219
168
|
}
|
|
220
169
|
return acc;
|
|
221
170
|
},
|
|
222
|
-
|
|
171
|
+
{}
|
|
223
172
|
);
|
|
224
173
|
|
|
225
174
|
return flattened;
|
|
@@ -228,25 +177,21 @@ export function getNonDefaultServerArgs(parsedArgs) {
|
|
|
228
177
|
const args = flatten(parsedArgs);
|
|
229
178
|
|
|
230
179
|
// hopefully these function names are descriptive enough
|
|
231
|
-
const typesDiffer =
|
|
180
|
+
const typesDiffer = (dest: string): boolean =>
|
|
232
181
|
typeof args[dest].value !== typeof defaultsFromSchema[dest];
|
|
233
182
|
|
|
234
|
-
const defaultValueIsArray =
|
|
235
|
-
_.isArray(defaultsFromSchema[dest]);
|
|
183
|
+
const defaultValueIsArray = (dest: string): boolean => _.isArray(defaultsFromSchema[dest]);
|
|
236
184
|
|
|
237
|
-
const argsValueIsArray =
|
|
185
|
+
const argsValueIsArray = (dest: string): boolean => _.isArray(args[dest].value);
|
|
238
186
|
|
|
239
|
-
const arraysDiffer =
|
|
240
|
-
_.gt(_.size(_.difference(args[dest].value, defaultsFromSchema[dest])), 0);
|
|
187
|
+
const arraysDiffer = (dest: string): boolean =>
|
|
188
|
+
_.gt(_.size(_.difference(args[dest].value as any[], defaultsFromSchema[dest] as any[])), 0);
|
|
241
189
|
|
|
242
|
-
const valuesDiffer =
|
|
243
|
-
args[dest].value !== defaultsFromSchema[dest];
|
|
190
|
+
const valuesDiffer = (dest: string): boolean => args[dest].value !== defaultsFromSchema[dest];
|
|
244
191
|
|
|
245
|
-
const defaultIsDefined =
|
|
246
|
-
!_.isUndefined(defaultsFromSchema[dest]);
|
|
192
|
+
const defaultIsDefined = (dest: string): boolean => !_.isUndefined(defaultsFromSchema[dest]);
|
|
247
193
|
|
|
248
194
|
// note that `_.overEvery` is like an "AND", and `_.overSome` is like an "OR"
|
|
249
|
-
|
|
250
195
|
const argValueNotArrayOrArraysDiffer = _.overSome([_.negate(argsValueIsArray), arraysDiffer]);
|
|
251
196
|
|
|
252
197
|
const defaultValueNotArrayAndValuesDiffer = _.overEvery([
|
|
@@ -264,7 +209,6 @@ export function getNonDefaultServerArgs(parsedArgs) {
|
|
|
264
209
|
* - if so, and the default is an array:
|
|
265
210
|
* - ensures the args value is an array
|
|
266
211
|
* - ensures the args values do not differ from the default values
|
|
267
|
-
* @type {(dest: string) => boolean}
|
|
268
212
|
*/
|
|
269
213
|
const isNotDefault = _.overEvery([
|
|
270
214
|
defaultIsDefined,
|
|
@@ -275,42 +219,29 @@ export function getNonDefaultServerArgs(parsedArgs) {
|
|
|
275
219
|
]),
|
|
276
220
|
]);
|
|
277
221
|
|
|
278
|
-
const defaultsFromSchema = getDefaultsForSchema(true)
|
|
222
|
+
const defaultsFromSchema = getDefaultsForSchema(true) as Record<string, unknown>;
|
|
279
223
|
|
|
280
224
|
return _.reduce(
|
|
281
|
-
_.pickBy(args, (
|
|
225
|
+
_.pickBy(args, (_v, key) => isNotDefault(key)),
|
|
282
226
|
// explodes the flattened object back into nested one
|
|
283
|
-
(acc, {value, argSpec}) => _.set(acc, argSpec.dest, value),
|
|
284
|
-
|
|
227
|
+
(acc: Args, {value, argSpec}: FlattenedArg) => _.set(acc, argSpec.dest, value),
|
|
228
|
+
{} as Args
|
|
285
229
|
);
|
|
286
230
|
}
|
|
287
231
|
|
|
288
|
-
/**
|
|
289
|
-
* Compacts an object for {@link showConfig}:
|
|
290
|
-
* 1. Removes `subcommand` key/value
|
|
291
|
-
* 2. Removes `undefined` values
|
|
292
|
-
* 3. Removes empty objects (but not `false` values)
|
|
293
|
-
* Does not operate recursively.
|
|
294
|
-
*/
|
|
295
|
-
const compactConfig = _.partial(
|
|
296
|
-
_.omitBy,
|
|
297
|
-
_,
|
|
298
|
-
(value, key) =>
|
|
299
|
-
key === 'subcommand' || _.isUndefined(value) || (_.isObject(value) && _.isEmpty(value))
|
|
300
|
-
);
|
|
301
|
-
|
|
302
232
|
/**
|
|
303
233
|
* Shows a breakdown of the current config after CLI params, config file loaded & defaults applied.
|
|
304
234
|
*
|
|
305
|
-
* The actual shape of `preConfigParsedArgs` and `defaults` does not matter for the purposes of this
|
|
306
|
-
* but it's intended to be called with values of type {@link ParsedArgs} and
|
|
307
|
-
*
|
|
308
|
-
* @param {Partial<ParsedArgs>} nonDefaultPreConfigParsedArgs - Parsed CLI args (or param to `init()`) before config & defaults applied
|
|
309
|
-
* @param {import('./config-file').ReadConfigFileResult} configResult - Result of attempting to load a config file. _Must_ be normalized
|
|
310
|
-
* @param {Partial<ParsedArgs>} defaults - Configuration defaults from schemas
|
|
311
|
-
* @param {ParsedArgs} parsedArgs - Entire parsed args object
|
|
235
|
+
* The actual shape of `preConfigParsedArgs` and `defaults` does not matter for the purposes of this
|
|
236
|
+
* function, but it's intended to be called with values of type {@link ParsedArgs} and
|
|
237
|
+
* `DefaultValues<true>`, respectively.
|
|
312
238
|
*/
|
|
313
|
-
export function showConfig(
|
|
239
|
+
export function showConfig(
|
|
240
|
+
nonDefaultPreConfigParsedArgs: Partial<Args>,
|
|
241
|
+
configResult: ReadConfigFileResult,
|
|
242
|
+
defaults: Partial<Args>,
|
|
243
|
+
parsedArgs: Args
|
|
244
|
+
): void {
|
|
314
245
|
console.log('Appium Configuration\n');
|
|
315
246
|
console.log('from defaults:\n');
|
|
316
247
|
console.dir(compactConfig(defaults));
|
|
@@ -332,17 +263,22 @@ export function showConfig(nonDefaultPreConfigParsedArgs, configResult, defaults
|
|
|
332
263
|
}
|
|
333
264
|
|
|
334
265
|
/**
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
266
|
+
* Ensures a directory exists and (optionally) is writeable.
|
|
267
|
+
*
|
|
268
|
+
* If the directory does not exist, this attempts to create it recursively.
|
|
269
|
+
*
|
|
338
270
|
* @throws {Error}
|
|
339
271
|
*/
|
|
340
|
-
export async function requireDir(
|
|
272
|
+
export async function requireDir(
|
|
273
|
+
root: string,
|
|
274
|
+
requireWriteable = true,
|
|
275
|
+
displayName = 'folder path'
|
|
276
|
+
): Promise<void> {
|
|
341
277
|
let stat;
|
|
342
278
|
try {
|
|
343
279
|
stat = await fs.stat(root);
|
|
344
280
|
} catch (e) {
|
|
345
|
-
if (e.code === 'ENOENT') {
|
|
281
|
+
if ((e as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
346
282
|
try {
|
|
347
283
|
await fs.mkdir(root, {recursive: true});
|
|
348
284
|
return;
|
|
@@ -358,23 +294,70 @@ export async function requireDir(root, requireWriteable = true, displayName = 'f
|
|
|
358
294
|
await fs.access(root, fs.constants.W_OK);
|
|
359
295
|
} catch {
|
|
360
296
|
throw new Error(
|
|
361
|
-
`The ${displayName} '${root}' must be `
|
|
362
|
-
`writeable for the current user account '${os.userInfo().username}'`
|
|
297
|
+
`The ${displayName} '${root}' must be writeable for the current user account '${os.userInfo().username}'`
|
|
363
298
|
);
|
|
364
299
|
}
|
|
365
300
|
}
|
|
366
301
|
}
|
|
367
302
|
|
|
303
|
+
function getNodeVersion(): semver.SemVer {
|
|
304
|
+
return semver.coerce(process.version) as semver.SemVer;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const getFullGitPath = _.memoize(async function getFullGitPath(): Promise<string | null> {
|
|
308
|
+
try {
|
|
309
|
+
return await fs.which(GIT_BINARY);
|
|
310
|
+
} catch {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
async function getGitTimestamp(commitSha: string, useGithubApiFallback = false): Promise<string | null> {
|
|
316
|
+
const fullGitPath = await getFullGitPath();
|
|
317
|
+
if (fullGitPath) {
|
|
318
|
+
try {
|
|
319
|
+
const {stdout} = await exec(fullGitPath, ['show', '-s', '--format=%ci', commitSha], {
|
|
320
|
+
cwd: __dirname,
|
|
321
|
+
});
|
|
322
|
+
return stdout.trim();
|
|
323
|
+
} catch {}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (!useGithubApiFallback) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
try {
|
|
331
|
+
return (
|
|
332
|
+
await axios.get(`${GITHUB_API}/git/tags/${commitSha}`, {
|
|
333
|
+
headers: {
|
|
334
|
+
'User-Agent': `Appium ${APPIUM_VER}`,
|
|
335
|
+
},
|
|
336
|
+
})
|
|
337
|
+
).data?.tagger?.date;
|
|
338
|
+
} catch {}
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Compacts an object for {@link showConfig}:
|
|
344
|
+
* 1. Removes `subcommand` key/value
|
|
345
|
+
* 2. Removes `undefined` values
|
|
346
|
+
* 3. Removes empty objects (but not `false` values)
|
|
347
|
+
* Does not operate recursively.
|
|
348
|
+
*/
|
|
349
|
+
const compactConfig = _.partial(
|
|
350
|
+
_.omitBy,
|
|
351
|
+
_,
|
|
352
|
+
(value: unknown, key: string) =>
|
|
353
|
+
key === 'subcommand' || _.isUndefined(value) || (_.isObject(value) && _.isEmpty(value))
|
|
354
|
+
);
|
|
355
|
+
|
|
368
356
|
/**
|
|
369
357
|
* Calculates the result of the given function and return its value
|
|
370
358
|
* or the default one if there was an exception.
|
|
371
|
-
*
|
|
372
|
-
* @template T
|
|
373
|
-
* @param {() => Promise<T>} f
|
|
374
|
-
* @param {T} defaultValue
|
|
375
|
-
* @returns {Promise<T>}
|
|
376
359
|
*/
|
|
377
|
-
async function getSafeResult(f
|
|
360
|
+
async function getSafeResult<T>(f: () => Promise<T>, defaultValue: T): Promise<T> {
|
|
378
361
|
try {
|
|
379
362
|
return await f();
|
|
380
363
|
} catch {
|
|
@@ -382,8 +365,13 @@ async function getSafeResult(f, defaultValue) {
|
|
|
382
365
|
}
|
|
383
366
|
}
|
|
384
367
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
368
|
+
interface DebugInfoInput {
|
|
369
|
+
driverConfig: {installedExtensions: unknown};
|
|
370
|
+
pluginConfig: {installedExtensions: unknown};
|
|
371
|
+
appiumHome: string;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
interface FlattenedArg {
|
|
375
|
+
value: unknown;
|
|
376
|
+
argSpec: {dest: string};
|
|
377
|
+
}
|
|
@@ -20,7 +20,6 @@ export const SERVER_SUBCOMMAND = 'server';
|
|
|
20
20
|
*/
|
|
21
21
|
export const SETUP_SUBCOMMAND = 'setup';
|
|
22
22
|
|
|
23
|
-
|
|
24
23
|
/**
|
|
25
24
|
* The value of `--use-plugins` if _all_ plugins should be loaded
|
|
26
25
|
*/
|
|
@@ -30,51 +29,41 @@ export const USE_ALL_PLUGINS = 'all';
|
|
|
30
29
|
// The plugins in this list will be available to the CLI so users can just
|
|
31
30
|
// type 'appium plugin install 'name'', rather than having to specify the full
|
|
32
31
|
// npm package. I.e., these are the officially recognized plugins.
|
|
33
|
-
export const KNOWN_PLUGINS = Object.freeze(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
export const DESKTOP_BROWSERS = Object.freeze(
|
|
60
|
-
/** @type {const} */ ({
|
|
61
|
-
safari: 'appium-safari-driver',
|
|
62
|
-
gecko: 'appium-geckodriver',
|
|
63
|
-
chromium: 'appium-chromium-driver',
|
|
64
|
-
}),
|
|
65
|
-
);
|
|
32
|
+
export const KNOWN_PLUGINS = Object.freeze({
|
|
33
|
+
'execute-driver': '@appium/execute-driver-plugin',
|
|
34
|
+
images: '@appium/images-plugin',
|
|
35
|
+
inspector: 'appium-inspector-plugin',
|
|
36
|
+
'relaxed-caps': '@appium/relaxed-caps-plugin',
|
|
37
|
+
storage: '@appium/storage-plugin',
|
|
38
|
+
'universal-xml': '@appium/universal-xml-plugin',
|
|
39
|
+
} as const);
|
|
40
|
+
|
|
41
|
+
export const MOBILE_DRIVERS = Object.freeze({
|
|
42
|
+
uiautomator2: 'appium-uiautomator2-driver',
|
|
43
|
+
xcuitest: 'appium-xcuitest-driver',
|
|
44
|
+
espresso: 'appium-espresso-driver',
|
|
45
|
+
} as const);
|
|
46
|
+
|
|
47
|
+
export const DESKTOP_DRIVERS = Object.freeze({
|
|
48
|
+
mac2: 'appium-mac2-driver',
|
|
49
|
+
windows: 'appium-windows-driver',
|
|
50
|
+
} as const);
|
|
51
|
+
|
|
52
|
+
export const DESKTOP_BROWSERS = Object.freeze({
|
|
53
|
+
safari: 'appium-safari-driver',
|
|
54
|
+
gecko: 'appium-geckodriver',
|
|
55
|
+
chromium: 'appium-chromium-driver',
|
|
56
|
+
} as const);
|
|
66
57
|
|
|
67
58
|
// This is a map of driver names to npm packages representing those drivers.
|
|
68
59
|
// The drivers in this list will be available to the CLI so users can just
|
|
69
60
|
// type 'appium driver install 'name'', rather than having to specify the full
|
|
70
61
|
// npm package. I.e., these are the officially recognized drivers.
|
|
71
|
-
export const KNOWN_DRIVERS = Object.freeze(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}),
|
|
77
|
-
);
|
|
62
|
+
export const KNOWN_DRIVERS = Object.freeze({
|
|
63
|
+
...MOBILE_DRIVERS,
|
|
64
|
+
...DESKTOP_DRIVERS,
|
|
65
|
+
...DESKTOP_BROWSERS,
|
|
66
|
+
} as const);
|
|
78
67
|
|
|
79
68
|
/**
|
|
80
69
|
* Relative path to directory containing any Appium internal files
|