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
package/lib/config-file.js
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import betterAjvErrors from '@sidvind/better-ajv-errors';
|
|
2
|
-
import {lilconfig} from 'lilconfig';
|
|
3
|
-
import _ from 'lodash';
|
|
4
|
-
import * as yaml from 'yaml';
|
|
5
|
-
import {getSchema, validate} from './schema/schema';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* lilconfig loader to handle `.yaml` files
|
|
9
|
-
* @type {import('lilconfig').LoaderSync}
|
|
10
|
-
*/
|
|
11
|
-
function yamlLoader(filepath, content) {
|
|
12
|
-
try {
|
|
13
|
-
return yaml.parse(content);
|
|
14
|
-
} catch (e) {
|
|
15
|
-
throw new Error(`The YAML config at '${filepath}' cannot be loaded. Original error: ${e.message}`);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* A cache of the raw config file (a JSON string) at a filepath.
|
|
21
|
-
* This is used for better error reporting.
|
|
22
|
-
* Note that config files needn't be JSON, but it helps if they are.
|
|
23
|
-
* @type {Map<string,RawJson>}
|
|
24
|
-
*/
|
|
25
|
-
const rawConfig = new Map();
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Custom JSON loader that caches the raw config file (for use with `better-ajv-errors`).
|
|
29
|
-
* If it weren't for this cache, this would be unnecessary.
|
|
30
|
-
* @type {import('lilconfig').LoaderSync}
|
|
31
|
-
*/
|
|
32
|
-
function jsonLoader(filepath, content) {
|
|
33
|
-
rawConfig.set(filepath, content);
|
|
34
|
-
try {
|
|
35
|
-
return JSON.parse(content);
|
|
36
|
-
} catch (e) {
|
|
37
|
-
throw new Error(`The JSON config at '${filepath}' cannot be loaded. Original error: ${e.message}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Loads a config file from an explicit path
|
|
43
|
-
* @param {LilconfigAsyncSearcher} lc - lilconfig instance
|
|
44
|
-
* @param {string} filepath - Path to config file
|
|
45
|
-
* @returns {Promise<import('lilconfig').LilconfigResult>}
|
|
46
|
-
*/
|
|
47
|
-
async function loadConfigFile(lc, filepath) {
|
|
48
|
-
try {
|
|
49
|
-
// removing "await" will cause any rejection to _not_ be caught in this block!
|
|
50
|
-
return await lc.load(filepath);
|
|
51
|
-
} catch (/** @type {unknown} */ err) {
|
|
52
|
-
if (/** @type {NodeJS.ErrnoException} */ (err).code === 'ENOENT') {
|
|
53
|
-
/** @type {NodeJS.ErrnoException} */ (
|
|
54
|
-
err
|
|
55
|
-
).message = `Config file not found at user-provided path: ${filepath}`;
|
|
56
|
-
throw err;
|
|
57
|
-
} else if (err instanceof SyntaxError) {
|
|
58
|
-
// generally invalid JSON
|
|
59
|
-
err.message = `Config file at user-provided path ${filepath} is invalid:\n${err.message}`;
|
|
60
|
-
throw err;
|
|
61
|
-
}
|
|
62
|
-
throw err;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Searches for a config file
|
|
68
|
-
* @param {LilconfigAsyncSearcher} lc - lilconfig instance
|
|
69
|
-
* @returns {Promise<import('lilconfig').LilconfigResult>}
|
|
70
|
-
*/
|
|
71
|
-
async function searchConfigFile(lc) {
|
|
72
|
-
return await lc.search();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Given an array of errors and the result of loading a config file, generate a
|
|
77
|
-
* helpful string for the user.
|
|
78
|
-
*
|
|
79
|
-
* - If `opts` contains a `json` property, this should be the original JSON
|
|
80
|
-
* _string_ of the config file. This is only applicable if the config file
|
|
81
|
-
* was in JSON format. If present, it will associate line numbers with errors.
|
|
82
|
-
* - If `errors` happens to be empty, this will throw.
|
|
83
|
-
* @param {import('ajv').ErrorObject[]} errors - Non-empty array of errors. Required.
|
|
84
|
-
* @param {ReadConfigFileResult['config']|any} [config] -
|
|
85
|
-
* Configuration & metadata
|
|
86
|
-
* @param {FormatConfigErrorsOptions} [opts]
|
|
87
|
-
* @throws {TypeError} If `errors` is empty
|
|
88
|
-
* @returns {string}
|
|
89
|
-
*/
|
|
90
|
-
export function formatErrors(errors = [], config = {}, opts = {}) {
|
|
91
|
-
if (errors && !errors.length) {
|
|
92
|
-
throw new TypeError('Array of errors must be non-empty');
|
|
93
|
-
}
|
|
94
|
-
return betterAjvErrors(getSchema(opts.schemaId), config, errors, {
|
|
95
|
-
json: opts.json,
|
|
96
|
-
format: 'cli',
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Given an optional path, read a config file. Validates the config file.
|
|
102
|
-
*
|
|
103
|
-
* Call {@link validate} if you already have a config object.
|
|
104
|
-
* @param {string} [filepath] - Path to config file, if we have one
|
|
105
|
-
* @param {ReadConfigFileOptions} [opts] - Options
|
|
106
|
-
* @public
|
|
107
|
-
* @returns {Promise<ReadConfigFileResult>} Contains config and filepath, if found, and any errors
|
|
108
|
-
*/
|
|
109
|
-
export async function readConfigFile(filepath, opts = {}) {
|
|
110
|
-
const lc = lilconfig('appium', {
|
|
111
|
-
loaders: {
|
|
112
|
-
'.yaml': yamlLoader,
|
|
113
|
-
'.yml': yamlLoader,
|
|
114
|
-
'.json': jsonLoader,
|
|
115
|
-
noExt: jsonLoader,
|
|
116
|
-
},
|
|
117
|
-
packageProp: 'appiumConfig',
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const result = filepath ? await loadConfigFile(lc, filepath) : await searchConfigFile(lc);
|
|
121
|
-
|
|
122
|
-
if (result?.filepath && !result?.isEmpty) {
|
|
123
|
-
const {pretty = true} = opts;
|
|
124
|
-
try {
|
|
125
|
-
let configResult;
|
|
126
|
-
const errors = validate(result.config);
|
|
127
|
-
if (_.isEmpty(errors)) {
|
|
128
|
-
configResult = {...result, errors};
|
|
129
|
-
} else {
|
|
130
|
-
const reason = formatErrors(errors, result.config, {
|
|
131
|
-
json: rawConfig.get(result.filepath),
|
|
132
|
-
pretty,
|
|
133
|
-
});
|
|
134
|
-
configResult = reason ? {...result, errors, reason} : {...result, errors};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// normalize (to camel case) all top-level property names of the config file
|
|
138
|
-
configResult.config = normalizeConfig(/** @type {AppiumConfig} */ (configResult.config));
|
|
139
|
-
|
|
140
|
-
return configResult;
|
|
141
|
-
} finally {
|
|
142
|
-
// clean up the raw config file cache, which is only kept to better report errors.
|
|
143
|
-
rawConfig.delete(result.filepath);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return result ?? {};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Convert schema property names to either a) the value of the `appiumCliDest` property, if any; or b) camel-case
|
|
151
|
-
* @param {AppiumConfig} config - Configuration object
|
|
152
|
-
* @returns {NormalizedAppiumConfig} New object with camel-cased keys (or `dest` keys).
|
|
153
|
-
*/
|
|
154
|
-
export function normalizeConfig(config) {
|
|
155
|
-
const schema = getSchema();
|
|
156
|
-
/**
|
|
157
|
-
* @param {AppiumConfig} config
|
|
158
|
-
* @param {string} [section] - Keypath (lodash `_.get()` style) to section of config. If omitted, assume root Appium config schema
|
|
159
|
-
* @todo Rewrite as a loop
|
|
160
|
-
* @returns Normalized section of config
|
|
161
|
-
*/
|
|
162
|
-
const normalize = (config, section) => {
|
|
163
|
-
const obj = _.isUndefined(section) ? config : _.get(config, section, config);
|
|
164
|
-
|
|
165
|
-
const mappedObj = _.mapKeys(obj, (__, prop) =>
|
|
166
|
-
_.get(schema, `properties.server.properties[${prop}].appiumCliDest`, _.camelCase(prop))
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
return _.mapValues(mappedObj, (value, property) => {
|
|
170
|
-
const nextSection = section ? `${section}.${property}` : property;
|
|
171
|
-
return isSchemaTypeObject(schema.properties?.[property])
|
|
172
|
-
? normalize(config, nextSection)
|
|
173
|
-
: value;
|
|
174
|
-
});
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Returns `true` if the schema prop references an object, or if it's an object itself
|
|
179
|
-
* @param {import('ajv').SchemaObject|object} schema - Referencing schema object
|
|
180
|
-
*/
|
|
181
|
-
const isSchemaTypeObject = (schema) => Boolean(schema?.properties || schema?.type === 'object');
|
|
182
|
-
|
|
183
|
-
return normalize(config);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Result of calling {@link readConfigFile}.
|
|
188
|
-
* @typedef ReadConfigFileResult
|
|
189
|
-
* @property {import('ajv').ErrorObject[]} [errors] - Validation errors
|
|
190
|
-
* @property {string} [filepath] - The path to the config file, if found
|
|
191
|
-
* @property {boolean} [isEmpty] - If `true`, the config file exists but is empty
|
|
192
|
-
* @property {NormalizedAppiumConfig} [config] - The parsed configuration
|
|
193
|
-
* @property {string|import('@sidvind/better-ajv-errors').IOutputError[]} [reason] - Human-readable error messages and suggestions. If the `pretty` option is `true`, this will be a nice string to print.
|
|
194
|
-
*/
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Options for {@link readConfigFile}.
|
|
198
|
-
* @typedef ReadConfigFileOptions
|
|
199
|
-
* @property {boolean} [pretty=true] If `false`, do not use color and fancy formatting in the `reason` property of the {@link ReadConfigFileResult}. The value of `reason` is then suitable for machine-reading.
|
|
200
|
-
*/
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* This is an `AsyncSearcher` which is inexplicably _not_ exported by the `lilconfig` type definition.
|
|
204
|
-
* @typedef {ReturnType<import('lilconfig')["lilconfig"]>} LilconfigAsyncSearcher
|
|
205
|
-
*/
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* The contents of an Appium config file. Generated from schema
|
|
209
|
-
* @typedef {import('@appium/types').AppiumConfig} AppiumConfig
|
|
210
|
-
*/
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* The contents of an Appium config file with camelcased property names (and using `appiumCliDest` value if present). Generated from {@link AppiumConfig}
|
|
214
|
-
* @typedef {import('@appium/types').NormalizedAppiumConfig} NormalizedAppiumConfig
|
|
215
|
-
*/
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* The string should be a raw JSON string.
|
|
219
|
-
* @typedef {string} RawJson
|
|
220
|
-
*/
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Options for {@link formatErrors}.
|
|
224
|
-
* @typedef FormatConfigErrorsOptions
|
|
225
|
-
* @property {import('./config-file').RawJson} [json] - Raw JSON config (as string)
|
|
226
|
-
* @property {boolean} [pretty=true] - Whether to format errors as a CLI-friendly string
|
|
227
|
-
* @property {string} [schemaId] - Specific ID of a prop; otherwise entire schema
|
|
228
|
-
*/
|
package/lib/config.js
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
import _ from 'lodash';
|
|
3
|
-
import {system, fs, npm} from '@appium/support';
|
|
4
|
-
import axios from 'axios';
|
|
5
|
-
import {exec} from 'teen_process';
|
|
6
|
-
import * as semver from 'semver';
|
|
7
|
-
import os from 'node:os';
|
|
8
|
-
import {npmPackage} from './utils';
|
|
9
|
-
import B from 'bluebird';
|
|
10
|
-
import {getDefaultsForSchema, getAllArgSpecs} from './schema/schema';
|
|
11
|
-
|
|
12
|
-
export const APPIUM_VER = npmPackage.version;
|
|
13
|
-
const ENGINES = /** @type {Record<string,string>} */ (npmPackage.engines);
|
|
14
|
-
const MIN_NODE_VERSION = ENGINES.node;
|
|
15
|
-
export const rootDir = fs.findRoot(__dirname);
|
|
16
|
-
|
|
17
|
-
const GIT_BINARY = `git${system.isWindows() ? '.exe' : ''}`;
|
|
18
|
-
const GITHUB_API = 'https://api.github.com/repos/appium/appium';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @type {import('appium/types').BuildInfo}
|
|
22
|
-
*/
|
|
23
|
-
const BUILD_INFO = {
|
|
24
|
-
version: APPIUM_VER,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
function getNodeVersion() {
|
|
28
|
-
return /** @type {import('semver').SemVer} */ (semver.coerce(process.version));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @param {boolean} [useGithubApiFallback]
|
|
33
|
-
* @returns {Promise<void>}
|
|
34
|
-
*/
|
|
35
|
-
export async function updateBuildInfo(useGithubApiFallback = false) {
|
|
36
|
-
const sha = await getGitRev(useGithubApiFallback);
|
|
37
|
-
if (!sha) {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
BUILD_INFO['git-sha'] = sha;
|
|
41
|
-
const buildTimestamp = await getGitTimestamp(sha, useGithubApiFallback);
|
|
42
|
-
if (buildTimestamp) {
|
|
43
|
-
BUILD_INFO.built = buildTimestamp;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
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
|
-
/**
|
|
57
|
-
* Prints server debug into into the console.
|
|
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>}
|
|
65
|
-
*/
|
|
66
|
-
export async function showDebugInfo({driverConfig, pluginConfig, appiumHome}) {
|
|
67
|
-
const getNpmVersion = async () => {
|
|
68
|
-
const {stdout} = await npm.exec('--version', [], {cwd: process.cwd()});
|
|
69
|
-
return _.trim(stdout);
|
|
70
|
-
};
|
|
71
|
-
const findNpmLocation = async () => await fs.which(system.isWindows() ? 'npm.cmd' : 'npm');
|
|
72
|
-
const [npmVersion, npmLocation] = await B.all([
|
|
73
|
-
...([getNpmVersion, findNpmLocation].map((f) => getSafeResult(f, 'unknown'))),
|
|
74
|
-
/** @type {any} */ (updateBuildInfo()),
|
|
75
|
-
]);
|
|
76
|
-
const debugInfo = {
|
|
77
|
-
os: {
|
|
78
|
-
platform: os.platform(),
|
|
79
|
-
release: os.release(),
|
|
80
|
-
arch: os.arch(),
|
|
81
|
-
homedir: os.homedir(),
|
|
82
|
-
username: os.userInfo().username,
|
|
83
|
-
},
|
|
84
|
-
node: {
|
|
85
|
-
version: process.version,
|
|
86
|
-
arch: process.arch,
|
|
87
|
-
cwd: process.cwd(),
|
|
88
|
-
argv: process.argv,
|
|
89
|
-
env: process.env,
|
|
90
|
-
npm: {
|
|
91
|
-
location: npmLocation,
|
|
92
|
-
version: npmVersion,
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
appium: {
|
|
96
|
-
location: rootDir,
|
|
97
|
-
homedir: appiumHome,
|
|
98
|
-
build: getBuildInfo(),
|
|
99
|
-
drivers: driverConfig.installedExtensions,
|
|
100
|
-
plugins: pluginConfig.installedExtensions,
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
console.log(JSON.stringify(debugInfo, null, 2));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* @param {boolean} [useGithubApiFallback]
|
|
108
|
-
* @returns {Promise<string?>}
|
|
109
|
-
*/
|
|
110
|
-
export async function getGitRev(useGithubApiFallback = false) {
|
|
111
|
-
const fullGitPath = await getFullGitPath();
|
|
112
|
-
if (fullGitPath) {
|
|
113
|
-
try {
|
|
114
|
-
const {stdout} = await exec(fullGitPath, ['rev-parse', 'HEAD'], {
|
|
115
|
-
cwd: __dirname,
|
|
116
|
-
});
|
|
117
|
-
return stdout.trim();
|
|
118
|
-
} catch {}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (!useGithubApiFallback) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// If the package folder is not a valid git repository
|
|
126
|
-
// then fetch the corresponding tag info from GitHub
|
|
127
|
-
try {
|
|
128
|
-
return (
|
|
129
|
-
await axios.get(`${GITHUB_API}/git/refs/tags/appium@${APPIUM_VER}`, {
|
|
130
|
-
headers: {
|
|
131
|
-
'User-Agent': `Appium ${APPIUM_VER}`,
|
|
132
|
-
},
|
|
133
|
-
})
|
|
134
|
-
).data?.object?.sha;
|
|
135
|
-
} catch {}
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
|
|
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
|
-
/**
|
|
172
|
-
* Mutable object containing Appium build information. By default it
|
|
173
|
-
* only contains the Appium version, but is updated with the build timestamp
|
|
174
|
-
* and git commit hash asynchronously as soon as `updateBuildInfo` is called
|
|
175
|
-
* and succeeds.
|
|
176
|
-
* @returns {import('appium/types').BuildInfo}
|
|
177
|
-
*/
|
|
178
|
-
export function getBuildInfo() {
|
|
179
|
-
return BUILD_INFO;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* @returns {void}
|
|
184
|
-
* @throws {Error} If Node version is outside of the supported range
|
|
185
|
-
*/
|
|
186
|
-
export function checkNodeOk() {
|
|
187
|
-
const version = getNodeVersion();
|
|
188
|
-
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
|
-
);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export async function showBuildInfo() {
|
|
196
|
-
await updateBuildInfo(true);
|
|
197
|
-
console.log(JSON.stringify(getBuildInfo()));
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Returns k/v pairs of server arguments which are _not_ the defaults.
|
|
202
|
-
* @param {Args} parsedArgs
|
|
203
|
-
* @returns {Args}
|
|
204
|
-
*/
|
|
205
|
-
export function getNonDefaultServerArgs(parsedArgs) {
|
|
206
|
-
/**
|
|
207
|
-
* Flattens parsed args into a single level object for comparison with
|
|
208
|
-
* flattened defaults across server args and extension args.
|
|
209
|
-
* @param {Args} args
|
|
210
|
-
* @returns {Record<string, { value: any, argSpec: ArgSpec }>}
|
|
211
|
-
*/
|
|
212
|
-
const flatten = (args) => {
|
|
213
|
-
const argSpecs = getAllArgSpecs();
|
|
214
|
-
const flattened = _.reduce(
|
|
215
|
-
[...argSpecs.values()],
|
|
216
|
-
(acc, argSpec) => {
|
|
217
|
-
if (_.has(args, argSpec.dest)) {
|
|
218
|
-
acc[argSpec.dest] = {value: _.get(args, argSpec.dest), argSpec};
|
|
219
|
-
}
|
|
220
|
-
return acc;
|
|
221
|
-
},
|
|
222
|
-
/** @type {Record<string, { value: any, argSpec: ArgSpec }>} */ ({})
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
return flattened;
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
const args = flatten(parsedArgs);
|
|
229
|
-
|
|
230
|
-
// hopefully these function names are descriptive enough
|
|
231
|
-
const typesDiffer = /** @param {string} dest */ (dest) =>
|
|
232
|
-
typeof args[dest].value !== typeof defaultsFromSchema[dest];
|
|
233
|
-
|
|
234
|
-
const defaultValueIsArray = /** @param {string} dest */ (dest) =>
|
|
235
|
-
_.isArray(defaultsFromSchema[dest]);
|
|
236
|
-
|
|
237
|
-
const argsValueIsArray = /** @param {string} dest */ (dest) => _.isArray(args[dest].value);
|
|
238
|
-
|
|
239
|
-
const arraysDiffer = /** @param {string} dest */ (dest) =>
|
|
240
|
-
_.gt(_.size(_.difference(args[dest].value, defaultsFromSchema[dest])), 0);
|
|
241
|
-
|
|
242
|
-
const valuesDiffer = /** @param {string} dest */ (dest) =>
|
|
243
|
-
args[dest].value !== defaultsFromSchema[dest];
|
|
244
|
-
|
|
245
|
-
const defaultIsDefined = /** @param {string} dest */ (dest) =>
|
|
246
|
-
!_.isUndefined(defaultsFromSchema[dest]);
|
|
247
|
-
|
|
248
|
-
// note that `_.overEvery` is like an "AND", and `_.overSome` is like an "OR"
|
|
249
|
-
|
|
250
|
-
const argValueNotArrayOrArraysDiffer = _.overSome([_.negate(argsValueIsArray), arraysDiffer]);
|
|
251
|
-
|
|
252
|
-
const defaultValueNotArrayAndValuesDiffer = _.overEvery([
|
|
253
|
-
_.negate(defaultValueIsArray),
|
|
254
|
-
valuesDiffer,
|
|
255
|
-
]);
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* This used to be a hideous conditional, but it's broken up into a hideous function instead.
|
|
259
|
-
* hopefully this makes things a little more understandable.
|
|
260
|
-
* - checks if the default value is defined
|
|
261
|
-
* - if so, and the default is not an array:
|
|
262
|
-
* - ensures the types are the same
|
|
263
|
-
* - ensures the values are equal
|
|
264
|
-
* - if so, and the default is an array:
|
|
265
|
-
* - ensures the args value is an array
|
|
266
|
-
* - ensures the args values do not differ from the default values
|
|
267
|
-
* @type {(dest: string) => boolean}
|
|
268
|
-
*/
|
|
269
|
-
const isNotDefault = _.overEvery([
|
|
270
|
-
defaultIsDefined,
|
|
271
|
-
_.overSome([
|
|
272
|
-
typesDiffer,
|
|
273
|
-
_.overEvery([defaultValueIsArray, argValueNotArrayOrArraysDiffer]),
|
|
274
|
-
defaultValueNotArrayAndValuesDiffer,
|
|
275
|
-
]),
|
|
276
|
-
]);
|
|
277
|
-
|
|
278
|
-
const defaultsFromSchema = getDefaultsForSchema(true);
|
|
279
|
-
|
|
280
|
-
return _.reduce(
|
|
281
|
-
_.pickBy(args, (__, key) => isNotDefault(key)),
|
|
282
|
-
// explodes the flattened object back into nested one
|
|
283
|
-
(acc, {value, argSpec}) => _.set(acc, argSpec.dest, value),
|
|
284
|
-
/** @type {Args} */ ({})
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
|
|
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
|
-
/**
|
|
303
|
-
* Shows a breakdown of the current config after CLI params, config file loaded & defaults applied.
|
|
304
|
-
*
|
|
305
|
-
* The actual shape of `preConfigParsedArgs` and `defaults` does not matter for the purposes of this function,
|
|
306
|
-
* but it's intended to be called with values of type {@link ParsedArgs} and `DefaultValues<true>`, respectively.
|
|
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
|
|
312
|
-
*/
|
|
313
|
-
export function showConfig(nonDefaultPreConfigParsedArgs, configResult, defaults, parsedArgs) {
|
|
314
|
-
console.log('Appium Configuration\n');
|
|
315
|
-
console.log('from defaults:\n');
|
|
316
|
-
console.dir(compactConfig(defaults));
|
|
317
|
-
if (configResult.config) {
|
|
318
|
-
console.log(`\nfrom config file at ${configResult.filepath}:\n`);
|
|
319
|
-
console.dir(compactConfig(configResult.config));
|
|
320
|
-
} else {
|
|
321
|
-
console.log(`\n(no configuration file loaded)`);
|
|
322
|
-
}
|
|
323
|
-
const compactedNonDefaultPreConfigArgs = compactConfig(nonDefaultPreConfigParsedArgs);
|
|
324
|
-
if (_.isEmpty(compactedNonDefaultPreConfigArgs)) {
|
|
325
|
-
console.log(`\n(no CLI parameters provided)`);
|
|
326
|
-
} else {
|
|
327
|
-
console.log('\nvia CLI or function call:\n');
|
|
328
|
-
console.dir(compactedNonDefaultPreConfigArgs);
|
|
329
|
-
}
|
|
330
|
-
console.log('\nfinal configuration:\n');
|
|
331
|
-
console.dir(compactConfig(parsedArgs));
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* @param {string} root
|
|
336
|
-
* @param {boolean} [requireWriteable=true]
|
|
337
|
-
* @param {string} [displayName='folder path']
|
|
338
|
-
* @throws {Error}
|
|
339
|
-
*/
|
|
340
|
-
export async function requireDir(root, requireWriteable = true, displayName = 'folder path') {
|
|
341
|
-
let stat;
|
|
342
|
-
try {
|
|
343
|
-
stat = await fs.stat(root);
|
|
344
|
-
} catch (e) {
|
|
345
|
-
if (e.code === 'ENOENT') {
|
|
346
|
-
try {
|
|
347
|
-
await fs.mkdir(root, {recursive: true});
|
|
348
|
-
return;
|
|
349
|
-
} catch {}
|
|
350
|
-
}
|
|
351
|
-
throw new Error(`The ${displayName} '${root}' must exist and be a valid directory`);
|
|
352
|
-
}
|
|
353
|
-
if (stat && !stat.isDirectory()) {
|
|
354
|
-
throw new Error(`The ${displayName} '${root}' must be a valid directory`);
|
|
355
|
-
}
|
|
356
|
-
if (requireWriteable) {
|
|
357
|
-
try {
|
|
358
|
-
await fs.access(root, fs.constants.W_OK);
|
|
359
|
-
} catch {
|
|
360
|
-
throw new Error(
|
|
361
|
-
`The ${displayName} '${root}' must be ` +
|
|
362
|
-
`writeable for the current user account '${os.userInfo().username}'`
|
|
363
|
-
);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Calculates the result of the given function and return its value
|
|
370
|
-
* 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
|
-
*/
|
|
377
|
-
async function getSafeResult(f, defaultValue) {
|
|
378
|
-
try {
|
|
379
|
-
return await f();
|
|
380
|
-
} catch {
|
|
381
|
-
return defaultValue;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* @typedef {import('appium/types').ParsedArgs} ParsedArgs
|
|
387
|
-
* @typedef {import('appium/types').Args} Args
|
|
388
|
-
* @typedef {import('./schema/arg-spec').ArgSpec} ArgSpec
|
|
389
|
-
*/
|