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.
Files changed (250) hide show
  1. package/build/lib/appium.d.ts +147 -205
  2. package/build/lib/appium.d.ts.map +1 -1
  3. package/build/lib/appium.js +169 -282
  4. package/build/lib/appium.js.map +1 -1
  5. package/build/lib/bidi-commands.d.ts.map +1 -1
  6. package/build/lib/bidi-commands.js +11 -11
  7. package/build/lib/bidi-commands.js.map +1 -1
  8. package/build/lib/bootstrap/appium-initializer.d.ts +21 -0
  9. package/build/lib/bootstrap/appium-initializer.d.ts.map +1 -0
  10. package/build/lib/bootstrap/appium-initializer.js +146 -0
  11. package/build/lib/bootstrap/appium-initializer.js.map +1 -0
  12. package/build/lib/bootstrap/appium-main-runner.d.ts +22 -0
  13. package/build/lib/bootstrap/appium-main-runner.d.ts.map +1 -0
  14. package/build/lib/bootstrap/appium-main-runner.js +109 -0
  15. package/build/lib/bootstrap/appium-main-runner.js.map +1 -0
  16. package/build/lib/bootstrap/config-file.d.ts +37 -0
  17. package/build/lib/bootstrap/config-file.d.ts.map +1 -0
  18. package/build/lib/{config-file.js → bootstrap/config-file.js} +62 -138
  19. package/build/lib/bootstrap/config-file.js.map +1 -0
  20. package/build/lib/bootstrap/grid-v3-register.d.ts +20 -0
  21. package/build/lib/bootstrap/grid-v3-register.d.ts.map +1 -0
  22. package/build/lib/bootstrap/grid-v3-register.js +185 -0
  23. package/build/lib/bootstrap/grid-v3-register.js.map +1 -0
  24. package/build/lib/bootstrap/init-types.d.ts +16 -0
  25. package/build/lib/bootstrap/init-types.d.ts.map +1 -0
  26. package/build/lib/bootstrap/init-types.js +3 -0
  27. package/build/lib/bootstrap/init-types.js.map +1 -0
  28. package/build/lib/bootstrap/main-helpers.d.ts +55 -0
  29. package/build/lib/bootstrap/main-helpers.d.ts.map +1 -0
  30. package/build/lib/bootstrap/main-helpers.js +187 -0
  31. package/build/lib/bootstrap/main-helpers.js.map +1 -0
  32. package/build/lib/bootstrap/node-helpers.d.ts +32 -0
  33. package/build/lib/bootstrap/node-helpers.d.ts.map +1 -0
  34. package/build/lib/bootstrap/node-helpers.js +201 -0
  35. package/build/lib/bootstrap/node-helpers.js.map +1 -0
  36. package/build/lib/bootstrap/startup-config.d.ts +22 -0
  37. package/build/lib/bootstrap/startup-config.d.ts.map +1 -0
  38. package/build/lib/bootstrap/startup-config.js +111 -0
  39. package/build/lib/bootstrap/startup-config.js.map +1 -0
  40. package/build/lib/cli/args.d.ts +16 -12
  41. package/build/lib/cli/args.d.ts.map +1 -1
  42. package/build/lib/cli/args.js +20 -40
  43. package/build/lib/cli/args.js.map +1 -1
  44. package/build/lib/cli/driver-command.d.ts +51 -93
  45. package/build/lib/cli/driver-command.d.ts.map +1 -1
  46. package/build/lib/cli/driver-command.js +11 -66
  47. package/build/lib/cli/driver-command.js.map +1 -1
  48. package/build/lib/cli/extension-command.d.ts +173 -377
  49. package/build/lib/cli/extension-command.d.ts.map +1 -1
  50. package/build/lib/cli/extension-command.js +387 -656
  51. package/build/lib/cli/extension-command.js.map +1 -1
  52. package/build/lib/cli/extension.d.ts +10 -15
  53. package/build/lib/cli/extension.d.ts.map +1 -1
  54. package/build/lib/cli/extension.js +15 -33
  55. package/build/lib/cli/extension.js.map +1 -1
  56. package/build/lib/cli/parser.d.ts +37 -66
  57. package/build/lib/cli/parser.d.ts.map +1 -1
  58. package/build/lib/cli/parser.js +69 -104
  59. package/build/lib/cli/parser.js.map +1 -1
  60. package/build/lib/cli/plugin-command.d.ts +50 -90
  61. package/build/lib/cli/plugin-command.d.ts.map +1 -1
  62. package/build/lib/cli/plugin-command.js +11 -63
  63. package/build/lib/cli/plugin-command.js.map +1 -1
  64. package/build/lib/cli/setup-command.d.ts +21 -26
  65. package/build/lib/cli/setup-command.d.ts.map +1 -1
  66. package/build/lib/cli/setup-command.js +19 -61
  67. package/build/lib/cli/setup-command.js.map +1 -1
  68. package/build/lib/cli/utils.d.ts +33 -35
  69. package/build/lib/cli/utils.d.ts.map +1 -1
  70. package/build/lib/cli/utils.js +48 -50
  71. package/build/lib/cli/utils.js.map +1 -1
  72. package/build/lib/constants.d.ts +23 -23
  73. package/build/lib/constants.d.ts.map +1 -1
  74. package/build/lib/constants.js +10 -15
  75. package/build/lib/constants.js.map +1 -1
  76. package/build/lib/doctor/doctor.d.ts +40 -57
  77. package/build/lib/doctor/doctor.d.ts.map +1 -1
  78. package/build/lib/doctor/doctor.js +31 -62
  79. package/build/lib/doctor/doctor.js.map +1 -1
  80. package/build/lib/extension/driver-config.d.ts +18 -77
  81. package/build/lib/extension/driver-config.d.ts.map +1 -1
  82. package/build/lib/extension/driver-config.js +37 -125
  83. package/build/lib/extension/driver-config.js.map +1 -1
  84. package/build/lib/extension/extension-config.d.ts +103 -210
  85. package/build/lib/extension/extension-config.d.ts.map +1 -1
  86. package/build/lib/extension/extension-config.js +180 -342
  87. package/build/lib/extension/extension-config.js.map +1 -1
  88. package/build/lib/extension/index.d.ts +12 -29
  89. package/build/lib/extension/index.d.ts.map +1 -1
  90. package/build/lib/extension/index.js +33 -75
  91. package/build/lib/extension/index.js.map +1 -1
  92. package/build/lib/extension/manifest-migrations.d.ts +3 -20
  93. package/build/lib/extension/manifest-migrations.d.ts.map +1 -1
  94. package/build/lib/extension/manifest-migrations.js +20 -101
  95. package/build/lib/extension/manifest-migrations.js.map +1 -1
  96. package/build/lib/extension/manifest.d.ts +61 -107
  97. package/build/lib/extension/manifest.d.ts.map +1 -1
  98. package/build/lib/extension/manifest.js +181 -356
  99. package/build/lib/extension/manifest.js.map +1 -1
  100. package/build/lib/extension/package-changed.d.ts +1 -3
  101. package/build/lib/extension/package-changed.d.ts.map +1 -1
  102. package/build/lib/extension/package-changed.js +8 -15
  103. package/build/lib/extension/package-changed.js.map +1 -1
  104. package/build/lib/extension/plugin-config.d.ts +10 -52
  105. package/build/lib/extension/plugin-config.d.ts.map +1 -1
  106. package/build/lib/extension/plugin-config.js +11 -63
  107. package/build/lib/extension/plugin-config.js.map +1 -1
  108. package/build/lib/helpers/build.d.ts +22 -0
  109. package/build/lib/helpers/build.d.ts.map +1 -0
  110. package/build/lib/helpers/build.js +109 -0
  111. package/build/lib/helpers/build.js.map +1 -0
  112. package/build/lib/helpers/capability.d.ts +38 -0
  113. package/build/lib/helpers/capability.d.ts.map +1 -0
  114. package/build/lib/helpers/capability.js +128 -0
  115. package/build/lib/helpers/capability.js.map +1 -0
  116. package/build/lib/helpers/network.d.ts +14 -0
  117. package/build/lib/helpers/network.d.ts.map +1 -0
  118. package/build/lib/helpers/network.js +35 -0
  119. package/build/lib/helpers/network.js.map +1 -0
  120. package/build/lib/insecure-features.js +6 -6
  121. package/build/lib/insecure-features.js.map +1 -1
  122. package/build/lib/inspector-commands.d.ts +6 -0
  123. package/build/lib/inspector-commands.d.ts.map +1 -1
  124. package/build/lib/inspector-commands.js +6 -0
  125. package/build/lib/inspector-commands.js.map +1 -1
  126. package/build/lib/logger.d.ts +2 -3
  127. package/build/lib/logger.d.ts.map +1 -1
  128. package/build/lib/logger.js +2 -3
  129. package/build/lib/logger.js.map +1 -1
  130. package/build/lib/logsink.d.ts +13 -22
  131. package/build/lib/logsink.d.ts.map +1 -1
  132. package/build/lib/logsink.js +48 -103
  133. package/build/lib/logsink.js.map +1 -1
  134. package/build/lib/main.d.ts +15 -58
  135. package/build/lib/main.d.ts.map +1 -1
  136. package/build/lib/main.js +25 -425
  137. package/build/lib/main.js.map +1 -1
  138. package/build/lib/schema/arg-spec.d.ts +32 -107
  139. package/build/lib/schema/arg-spec.d.ts.map +1 -1
  140. package/build/lib/schema/arg-spec.js +11 -107
  141. package/build/lib/schema/arg-spec.js.map +1 -1
  142. package/build/lib/schema/cli-args-guards.d.ts +34 -0
  143. package/build/lib/schema/cli-args-guards.d.ts.map +1 -0
  144. package/build/lib/schema/cli-args-guards.js +49 -0
  145. package/build/lib/schema/cli-args-guards.js.map +1 -0
  146. package/build/lib/schema/cli-args.d.ts +3 -15
  147. package/build/lib/schema/cli-args.d.ts.map +1 -1
  148. package/build/lib/schema/cli-args.js +17 -107
  149. package/build/lib/schema/cli-args.js.map +1 -1
  150. package/build/lib/schema/cli-transformers.d.ts +15 -12
  151. package/build/lib/schema/cli-transformers.d.ts.map +1 -1
  152. package/build/lib/schema/cli-transformers.js +15 -45
  153. package/build/lib/schema/cli-transformers.js.map +1 -1
  154. package/build/lib/schema/format-errors.d.ts +28 -0
  155. package/build/lib/schema/format-errors.d.ts.map +1 -0
  156. package/build/lib/schema/format-errors.js +29 -0
  157. package/build/lib/schema/format-errors.js.map +1 -0
  158. package/build/lib/schema/index.d.ts +4 -2
  159. package/build/lib/schema/index.d.ts.map +1 -1
  160. package/build/lib/schema/index.js +2 -0
  161. package/build/lib/schema/index.js.map +1 -1
  162. package/build/lib/schema/keywords.d.ts +12 -20
  163. package/build/lib/schema/keywords.d.ts.map +1 -1
  164. package/build/lib/schema/keywords.js +6 -51
  165. package/build/lib/schema/keywords.js.map +1 -1
  166. package/build/lib/schema/schema.d.ts +106 -231
  167. package/build/lib/schema/schema.d.ts.map +1 -1
  168. package/build/lib/schema/schema.js +88 -358
  169. package/build/lib/schema/schema.js.map +1 -1
  170. package/build/lib/utils.d.ts +7 -267
  171. package/build/lib/utils.d.ts.map +1 -1
  172. package/build/lib/utils.js +10 -409
  173. package/build/lib/utils.js.map +1 -1
  174. package/lib/{appium.js → appium.ts} +297 -341
  175. package/lib/bidi-commands.ts +10 -14
  176. package/lib/bootstrap/appium-initializer.ts +212 -0
  177. package/lib/bootstrap/appium-main-runner.ts +172 -0
  178. package/lib/bootstrap/config-file.ts +178 -0
  179. package/lib/bootstrap/grid-v3-register.ts +250 -0
  180. package/lib/bootstrap/init-types.ts +31 -0
  181. package/lib/bootstrap/main-helpers.ts +223 -0
  182. package/lib/bootstrap/node-helpers.ts +180 -0
  183. package/lib/bootstrap/startup-config.ts +143 -0
  184. package/lib/cli/{args.js → args.ts} +45 -56
  185. package/lib/cli/driver-command.ts +122 -0
  186. package/lib/cli/{extension-command.js → extension-command.ts} +827 -906
  187. package/lib/cli/extension.ts +65 -0
  188. package/lib/cli/{parser.js → parser.ts} +93 -116
  189. package/lib/cli/plugin-command.ts +117 -0
  190. package/lib/cli/{setup-command.js → setup-command.ts} +59 -74
  191. package/lib/cli/utils.ts +97 -0
  192. package/lib/{constants.js → constants.ts} +30 -41
  193. package/lib/doctor/{doctor.js → doctor.ts} +82 -92
  194. package/lib/extension/driver-config.ts +165 -0
  195. package/lib/extension/{extension-config.js → extension-config.ts} +291 -405
  196. package/lib/extension/index.ts +143 -0
  197. package/lib/extension/manifest-migrations.ts +57 -0
  198. package/lib/extension/manifest.ts +369 -0
  199. package/lib/extension/{package-changed.js → package-changed.ts} +9 -18
  200. package/lib/extension/plugin-config.ts +62 -0
  201. package/lib/helpers/build.ts +111 -0
  202. package/lib/helpers/capability.ts +171 -0
  203. package/lib/helpers/network.ts +30 -0
  204. package/lib/insecure-features.ts +1 -1
  205. package/lib/inspector-commands.ts +6 -1
  206. package/lib/{logger.js → logger.ts} +1 -2
  207. package/lib/{logsink.js → logsink.ts} +91 -137
  208. package/lib/main.ts +60 -0
  209. package/lib/schema/arg-spec.ts +131 -0
  210. package/lib/schema/cli-args-guards.ts +67 -0
  211. package/lib/schema/cli-args.ts +171 -0
  212. package/lib/schema/cli-transformers.ts +83 -0
  213. package/lib/schema/format-errors.ts +43 -0
  214. package/lib/schema/index.ts +4 -0
  215. package/lib/schema/keywords.ts +96 -0
  216. package/lib/schema/schema.ts +448 -0
  217. package/lib/utils.ts +73 -0
  218. package/package.json +17 -18
  219. package/scripts/autoinstall-extensions.js +3 -0
  220. package/build/lib/config-file.d.ts +0 -100
  221. package/build/lib/config-file.d.ts.map +0 -1
  222. package/build/lib/config-file.js.map +0 -1
  223. package/build/lib/config.d.ts +0 -70
  224. package/build/lib/config.d.ts.map +0 -1
  225. package/build/lib/config.js +0 -390
  226. package/build/lib/config.js.map +0 -1
  227. package/build/lib/grid-register.d.ts +0 -10
  228. package/build/lib/grid-register.d.ts.map +0 -1
  229. package/build/lib/grid-register.js +0 -134
  230. package/build/lib/grid-register.js.map +0 -1
  231. package/lib/cli/driver-command.js +0 -174
  232. package/lib/cli/extension.js +0 -74
  233. package/lib/cli/plugin-command.js +0 -164
  234. package/lib/cli/utils.js +0 -91
  235. package/lib/config-file.js +0 -228
  236. package/lib/config.js +0 -389
  237. package/lib/extension/driver-config.js +0 -245
  238. package/lib/extension/index.js +0 -169
  239. package/lib/extension/manifest-migrations.js +0 -136
  240. package/lib/extension/manifest.js +0 -550
  241. package/lib/extension/plugin-config.js +0 -112
  242. package/lib/grid-register.js +0 -146
  243. package/lib/main.js +0 -545
  244. package/lib/schema/arg-spec.js +0 -229
  245. package/lib/schema/cli-args.js +0 -254
  246. package/lib/schema/cli-transformers.js +0 -113
  247. package/lib/schema/index.js +0 -2
  248. package/lib/schema/keywords.js +0 -136
  249. package/lib/schema/schema.js +0 -725
  250. package/lib/utils.js +0 -512
@@ -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
- */