appium 3.3.0 → 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 (196) 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} +9 -26
  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/{grid-register.js → bootstrap/grid-v3-register.js} +28 -13
  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.map +1 -1
  41. package/build/lib/cli/args.js +9 -9
  42. package/build/lib/cli/args.js.map +1 -1
  43. package/build/lib/cli/extension-command.d.ts +95 -95
  44. package/build/lib/cli/extension-command.d.ts.map +1 -1
  45. package/build/lib/cli/extension-command.js +18 -18
  46. package/build/lib/cli/extension-command.js.map +1 -1
  47. package/build/lib/cli/extension.d.ts +1 -1
  48. package/build/lib/cli/extension.d.ts.map +1 -1
  49. package/build/lib/cli/extension.js +5 -5
  50. package/build/lib/cli/extension.js.map +1 -1
  51. package/build/lib/cli/parser.d.ts +8 -8
  52. package/build/lib/cli/parser.d.ts.map +1 -1
  53. package/build/lib/cli/parser.js +49 -49
  54. package/build/lib/cli/parser.js.map +1 -1
  55. package/build/lib/cli/setup-command.js +6 -6
  56. package/build/lib/cli/setup-command.js.map +1 -1
  57. package/build/lib/cli/utils.d.ts +17 -17
  58. package/build/lib/cli/utils.d.ts.map +1 -1
  59. package/build/lib/cli/utils.js +29 -29
  60. package/build/lib/cli/utils.js.map +1 -1
  61. package/build/lib/doctor/doctor.d.ts +2 -2
  62. package/build/lib/doctor/doctor.d.ts.map +1 -1
  63. package/build/lib/doctor/doctor.js +6 -6
  64. package/build/lib/doctor/doctor.js.map +1 -1
  65. package/build/lib/extension/driver-config.d.ts +18 -77
  66. package/build/lib/extension/driver-config.d.ts.map +1 -1
  67. package/build/lib/extension/driver-config.js +37 -125
  68. package/build/lib/extension/driver-config.js.map +1 -1
  69. package/build/lib/extension/extension-config.d.ts +103 -210
  70. package/build/lib/extension/extension-config.d.ts.map +1 -1
  71. package/build/lib/extension/extension-config.js +180 -342
  72. package/build/lib/extension/extension-config.js.map +1 -1
  73. package/build/lib/extension/index.d.ts +12 -29
  74. package/build/lib/extension/index.d.ts.map +1 -1
  75. package/build/lib/extension/index.js +33 -75
  76. package/build/lib/extension/index.js.map +1 -1
  77. package/build/lib/extension/manifest-migrations.d.ts +3 -20
  78. package/build/lib/extension/manifest-migrations.d.ts.map +1 -1
  79. package/build/lib/extension/manifest-migrations.js +20 -101
  80. package/build/lib/extension/manifest-migrations.js.map +1 -1
  81. package/build/lib/extension/manifest.d.ts +61 -107
  82. package/build/lib/extension/manifest.d.ts.map +1 -1
  83. package/build/lib/extension/manifest.js +181 -356
  84. package/build/lib/extension/manifest.js.map +1 -1
  85. package/build/lib/extension/package-changed.d.ts +1 -3
  86. package/build/lib/extension/package-changed.d.ts.map +1 -1
  87. package/build/lib/extension/package-changed.js +8 -15
  88. package/build/lib/extension/package-changed.js.map +1 -1
  89. package/build/lib/extension/plugin-config.d.ts +10 -52
  90. package/build/lib/extension/plugin-config.d.ts.map +1 -1
  91. package/build/lib/extension/plugin-config.js +11 -63
  92. package/build/lib/extension/plugin-config.js.map +1 -1
  93. package/build/lib/helpers/build.d.ts +22 -0
  94. package/build/lib/helpers/build.d.ts.map +1 -0
  95. package/build/lib/helpers/build.js +109 -0
  96. package/build/lib/helpers/build.js.map +1 -0
  97. package/build/lib/helpers/capability.d.ts +38 -0
  98. package/build/lib/helpers/capability.d.ts.map +1 -0
  99. package/build/lib/helpers/capability.js +128 -0
  100. package/build/lib/helpers/capability.js.map +1 -0
  101. package/build/lib/helpers/network.d.ts +14 -0
  102. package/build/lib/helpers/network.d.ts.map +1 -0
  103. package/build/lib/helpers/network.js +35 -0
  104. package/build/lib/helpers/network.js.map +1 -0
  105. package/build/lib/insecure-features.js +6 -6
  106. package/build/lib/insecure-features.js.map +1 -1
  107. package/build/lib/inspector-commands.d.ts +6 -0
  108. package/build/lib/inspector-commands.d.ts.map +1 -1
  109. package/build/lib/inspector-commands.js +6 -0
  110. package/build/lib/inspector-commands.js.map +1 -1
  111. package/build/lib/logger.d.ts +2 -3
  112. package/build/lib/logger.d.ts.map +1 -1
  113. package/build/lib/logger.js +2 -3
  114. package/build/lib/logger.js.map +1 -1
  115. package/build/lib/main.d.ts +15 -58
  116. package/build/lib/main.d.ts.map +1 -1
  117. package/build/lib/main.js +25 -425
  118. package/build/lib/main.js.map +1 -1
  119. package/build/lib/schema/cli-args-guards.d.ts +34 -0
  120. package/build/lib/schema/cli-args-guards.d.ts.map +1 -0
  121. package/build/lib/schema/cli-args-guards.js +49 -0
  122. package/build/lib/schema/cli-args-guards.js.map +1 -0
  123. package/build/lib/schema/cli-args.js +2 -2
  124. package/build/lib/schema/cli-args.js.map +1 -1
  125. package/build/lib/schema/format-errors.d.ts +28 -0
  126. package/build/lib/schema/format-errors.d.ts.map +1 -0
  127. package/build/lib/schema/format-errors.js +29 -0
  128. package/build/lib/schema/format-errors.js.map +1 -0
  129. package/build/lib/schema/index.d.ts +2 -0
  130. package/build/lib/schema/index.d.ts.map +1 -1
  131. package/build/lib/schema/index.js +2 -0
  132. package/build/lib/schema/index.js.map +1 -1
  133. package/build/lib/schema/schema.d.ts +15 -15
  134. package/build/lib/schema/schema.d.ts.map +1 -1
  135. package/build/lib/schema/schema.js +37 -37
  136. package/build/lib/schema/schema.js.map +1 -1
  137. package/build/lib/utils.d.ts +0 -81
  138. package/build/lib/utils.d.ts.map +1 -1
  139. package/build/lib/utils.js +1 -248
  140. package/build/lib/utils.js.map +1 -1
  141. package/lib/{appium.js → appium.ts} +297 -341
  142. package/lib/bidi-commands.ts +10 -14
  143. package/lib/bootstrap/appium-initializer.ts +212 -0
  144. package/lib/bootstrap/appium-main-runner.ts +172 -0
  145. package/lib/{config-file.ts → bootstrap/config-file.ts} +29 -63
  146. package/lib/{grid-register.ts → bootstrap/grid-v3-register.ts} +35 -35
  147. package/lib/bootstrap/init-types.ts +31 -0
  148. package/lib/bootstrap/main-helpers.ts +223 -0
  149. package/lib/bootstrap/node-helpers.ts +180 -0
  150. package/lib/bootstrap/startup-config.ts +143 -0
  151. package/lib/cli/args.ts +10 -10
  152. package/lib/cli/extension-command.ts +132 -132
  153. package/lib/cli/extension.ts +7 -7
  154. package/lib/cli/parser.ts +50 -50
  155. package/lib/cli/setup-command.ts +2 -2
  156. package/lib/cli/utils.ts +33 -33
  157. package/lib/doctor/doctor.ts +8 -8
  158. package/lib/extension/driver-config.ts +165 -0
  159. package/lib/extension/{extension-config.js → extension-config.ts} +291 -405
  160. package/lib/extension/index.ts +143 -0
  161. package/lib/extension/manifest-migrations.ts +57 -0
  162. package/lib/extension/manifest.ts +369 -0
  163. package/lib/extension/{package-changed.js → package-changed.ts} +9 -18
  164. package/lib/extension/plugin-config.ts +62 -0
  165. package/lib/helpers/build.ts +111 -0
  166. package/lib/helpers/capability.ts +171 -0
  167. package/lib/helpers/network.ts +30 -0
  168. package/lib/insecure-features.ts +1 -1
  169. package/lib/inspector-commands.ts +6 -1
  170. package/lib/{logger.js → logger.ts} +1 -2
  171. package/lib/main.ts +60 -0
  172. package/lib/schema/cli-args-guards.ts +67 -0
  173. package/lib/schema/cli-args.ts +1 -1
  174. package/lib/schema/format-errors.ts +43 -0
  175. package/lib/schema/index.ts +2 -0
  176. package/lib/schema/schema.ts +51 -52
  177. package/lib/utils.ts +0 -331
  178. package/package.json +12 -13
  179. package/scripts/autoinstall-extensions.js +3 -0
  180. package/build/lib/config-file.d.ts +0 -57
  181. package/build/lib/config-file.d.ts.map +0 -1
  182. package/build/lib/config-file.js.map +0 -1
  183. package/build/lib/config.d.ts +0 -68
  184. package/build/lib/config.d.ts.map +0 -1
  185. package/build/lib/config.js +0 -358
  186. package/build/lib/config.js.map +0 -1
  187. package/build/lib/grid-register.d.ts +0 -35
  188. package/build/lib/grid-register.d.ts.map +0 -1
  189. package/build/lib/grid-register.js.map +0 -1
  190. package/lib/config.ts +0 -377
  191. package/lib/extension/driver-config.js +0 -245
  192. package/lib/extension/index.js +0 -169
  193. package/lib/extension/manifest-migrations.js +0 -136
  194. package/lib/extension/manifest.js +0 -550
  195. package/lib/extension/plugin-config.js +0 -112
  196. package/lib/main.js +0 -545
@@ -1,550 +0,0 @@
1
- /**
2
- * Module containing {@link Manifest} which handles reading & writing of extension config files.
3
- */
4
-
5
- import B from 'bluebird';
6
- import {env, fs} from '@appium/support';
7
- import _ from 'lodash';
8
- import path from 'node:path';
9
- import * as YAML from 'yaml';
10
- import {CURRENT_SCHEMA_REV, DRIVER_TYPE, PLUGIN_TYPE} from '../constants';
11
- import {INSTALL_TYPE_NPM, INSTALL_TYPE_DEV} from './extension-config';
12
- import {packageDidChange} from './package-changed';
13
- import {migrate} from './manifest-migrations';
14
-
15
- /**
16
- * The name of the prop (`drivers`) used in `extensions.yaml` for drivers.
17
- * @type {`${typeof DRIVER_TYPE}s`}
18
- */
19
- const CONFIG_DATA_DRIVER_KEY = `${DRIVER_TYPE}s`;
20
-
21
- /**
22
- * The name of the prop (`plugins`) used in `extensions.yaml` for plugins.
23
- * @type {`${typeof PLUGIN_TYPE}s`}
24
- */
25
- const CONFIG_DATA_PLUGIN_KEY = `${PLUGIN_TYPE}s`;
26
-
27
- /**
28
- * @type {Readonly<ManifestData>}
29
- */
30
- const INITIAL_MANIFEST_DATA = Object.freeze({
31
- [CONFIG_DATA_DRIVER_KEY]: Object.freeze({}),
32
- [CONFIG_DATA_PLUGIN_KEY]: Object.freeze({}),
33
- schemaRev: CURRENT_SCHEMA_REV,
34
- });
35
-
36
- /**
37
- * Given a `package.json` return `true` if it represents an Appium Extension (either a driver or plugin).
38
- *
39
- * _This is a type guard; not a validator._
40
- *
41
- * The `package.json` must have an `appium` property which is an object.
42
- * @param {any} value
43
- * @returns {value is ExtPackageJson<ExtensionType>}
44
- */
45
- function isExtension(value) {
46
- return (
47
- _.isPlainObject(value) &&
48
- _.isPlainObject(value.appium) &&
49
- _.isString(value.name) &&
50
- _.isString(value.version)
51
- );
52
- }
53
-
54
- /**
55
- * Given a `package.json`, return `true` if it represents an Appium Driver.
56
- *
57
- * _This is a type guard; not a validator._
58
- *
59
- * To be considered a driver, a `package.json` must have an `appium.driverName` field.
60
- *
61
- * Further validation of the `appium` property happens elsewhere.
62
- * @param {any} value - Value to test
63
- * @returns {value is ExtPackageJson<DriverType>}
64
- */
65
- function isDriver(value) {
66
- return isExtension(value) && 'driverName' in value.appium && _.isString(value.appium.driverName);
67
- }
68
-
69
- /**
70
- * Given a `package.json`, return `true` if it represents an Appium Plugin.
71
- *
72
- * _This is a type guard; not a validator._
73
- *
74
- * To be considered a plugin, a `package.json` must have an `appium.pluginName` field.
75
- *
76
- * Further validation of the `appium` property happens elsewhere.
77
- * @param {any} value - Value to test
78
- * @returns {value is ExtPackageJson<PluginType>}
79
- */
80
- function isPlugin(value) {
81
- return isExtension(value) && 'pluginName' in value.appium && _.isString(value.appium.pluginName);
82
- }
83
-
84
- /**
85
- * Handles reading & writing of extension config files.
86
- *
87
- * Only one instance of this class exists per value of `APPIUM_HOME`.
88
- */
89
- export class Manifest {
90
- /**
91
- * The entire contents of a parsed YAML extension config file.
92
- *
93
- * Contains proxies for automatic persistence on disk
94
- * @type {ManifestData}
95
- */
96
- #data;
97
-
98
- /**
99
- * Path to `APPIUM_HOME`.
100
- * @type {Readonly<string>}
101
- */
102
- #appiumHome;
103
-
104
- /**
105
- * Path to `extensions.yaml`
106
- * @type {string}
107
- * Not set until {@link Manifest.read} is called.
108
- */
109
- #manifestPath;
110
-
111
- /**
112
- * Helps avoid writing multiple times.
113
- *
114
- * If this is `undefined`, calling {@link Manifest.write} will cause it to be
115
- * set to a `Promise`. When the call to `write()` is complete, the `Promise`
116
- * will resolve and then this value will be set to `undefined`. Concurrent calls
117
- * made while this value is a `Promise` will return the `Promise` itself.
118
- * @type {Promise<boolean>|undefined}
119
- */
120
- #writing;
121
-
122
- /**
123
- * Helps avoid reading multiple times.
124
- *
125
- * If this is `undefined`, calling {@link Manifest.read} will cause it to be
126
- * set to a `Promise`. When the call to `read()` is complete, the `Promise`
127
- * will resolve and then this value will be set to `undefined`. Concurrent calls
128
- * made while this value is a `Promise` will return the `Promise` itself.
129
- * @type {Promise<void>|undefined}
130
- */
131
- #reading;
132
-
133
- /**
134
- * Sets internal data to a fresh clone of {@link INITIAL_MANIFEST_DATA}
135
- *
136
- * Use {@link Manifest.getInstance} instead.
137
- * @param {string} appiumHome
138
- * @private
139
- */
140
- constructor(appiumHome) {
141
- this.#appiumHome = appiumHome;
142
- this.#data = _.cloneDeep(INITIAL_MANIFEST_DATA);
143
- }
144
-
145
- /**
146
- * Returns a new or existing {@link Manifest} instance, based on the value of `appiumHome`.
147
- *
148
- * Maintains one instance per value of `appiumHome`.
149
- */
150
- static getInstance = _.memoize(
151
- /**
152
- * @param {string} appiumHome - Path to `APPIUM_HOME`
153
- * @returns {Manifest}
154
- */
155
- function _getInstance(appiumHome) {
156
- return new Manifest(appiumHome);
157
- }
158
- );
159
-
160
- /**
161
- * Searches `APPIUM_HOME` for installed extensions and adds them to the manifest.
162
- * @param {boolean} hasAppiumDependency - This affects whether or not the "dev" `InstallType` is used
163
- * @returns {Promise<boolean>} `true` if any extensions were added, `false` otherwise.
164
- */
165
- async syncWithInstalledExtensions(hasAppiumDependency = false) {
166
- // this could be parallelized, but we can't use fs.walk as an async iterator
167
- let didChange = false;
168
-
169
- /**
170
- * Listener for the `match` event of a `glob` instance
171
- * @param {string} filepath - Path to a `package.json`
172
- * @param {boolean} [devType] - If `true`, this is an extension in "dev mode"
173
- * @returns {Promise<void>}
174
- */
175
- const onMatch = async (filepath, devType = false) => {
176
- try {
177
- const pkg = JSON.parse(await fs.readFile(filepath, 'utf8'));
178
- if (isExtension(pkg)) {
179
- const installType = devType && hasAppiumDependency ? INSTALL_TYPE_DEV : INSTALL_TYPE_NPM;
180
- const changed = this.addExtensionFromPackage(pkg, filepath, installType);
181
- didChange = didChange || changed;
182
- }
183
- } catch {}
184
- };
185
-
186
- /**
187
- * A list of `Promise`s which read `package.json` files looking for Appium extensions.
188
- * @type {Promise<void>[]}
189
- */
190
- const queue = [
191
- // look at `package.json` in `APPIUM_HOME` only.
192
- // this causes extensions in "dev mode" to be automatically found
193
- onMatch(path.join(this.#appiumHome, 'package.json'), true),
194
- ];
195
-
196
- // add dependencies to the queue
197
- const filepaths = await fs.glob('node_modules/{*,@*/*}/package.json', {
198
- cwd: this.#appiumHome,
199
- absolute: true,
200
- });
201
- for (const filepath of filepaths) {
202
- queue.push(onMatch(filepath));
203
- }
204
-
205
- // wait for everything to finish
206
- await B.all(queue);
207
-
208
- return didChange;
209
- }
210
-
211
- /**
212
- * Returns `true` if driver with name `name` is registered.
213
- * @param {string} name - Driver name
214
- * @returns {boolean}
215
- */
216
- hasDriver(name) {
217
- return Boolean(this.#data.drivers[name]);
218
- }
219
-
220
- /**
221
- * Returns `true` if plugin with name `name` is registered.
222
- * @param {string} name - Plugin name
223
- * @returns {boolean}
224
- */
225
- hasPlugin(name) {
226
- return Boolean(this.#data.plugins[name]);
227
- }
228
-
229
- /**
230
- * Given a path to a `package.json`, add it as either a driver or plugin to the manifest.
231
- *
232
- * @template {ExtensionType} ExtType
233
- * @param {ExtPackageJson<ExtType>} pkgJson
234
- * @param {string} pkgPath
235
- * @param {typeof INSTALL_TYPE_NPM | typeof INSTALL_TYPE_DEV} [installType]
236
- * @returns {boolean} - `true` if this method did anything.
237
- */
238
- addExtensionFromPackage(pkgJson, pkgPath, installType = INSTALL_TYPE_NPM) {
239
- const extensionPath = path.dirname(pkgPath);
240
-
241
- /**
242
- * @type {InternalMetadata}
243
- */
244
- const internal = {
245
- pkgName: /** @type {string} */ (pkgJson.name),
246
- version: /** @type {string} */ (pkgJson.version),
247
- appiumVersion: pkgJson.peerDependencies?.appium,
248
- installType,
249
- installSpec: `${pkgJson.name}@${pkgJson.version}`,
250
- installPath: extensionPath,
251
- };
252
-
253
- if (isDriver(pkgJson)) {
254
- const value = {
255
- ..._.omit(pkgJson.appium, 'driverName'),
256
- ...internal,
257
- };
258
- if (!_.isEqual(value, this.#data.drivers[pkgJson.appium.driverName])) {
259
- this.setExtension(
260
- /** @type {ExtType} */ (DRIVER_TYPE),
261
- pkgJson.appium.driverName,
262
- /** @type {ExtManifest<ExtType>} */ (value)
263
- );
264
- return true;
265
- }
266
- return false;
267
- } else if (isPlugin(pkgJson)) {
268
- const value = {
269
- ..._.omit(pkgJson.appium, 'pluginName'),
270
- ...internal,
271
- };
272
- if (!_.isEqual(value, this.#data.plugins[pkgJson.appium.pluginName])) {
273
- this.setExtension(
274
- /** @type {ExtType} */ (PLUGIN_TYPE),
275
- pkgJson.appium.pluginName,
276
- /** @type {ExtManifest<ExtType>} */ (value)
277
- );
278
- return true;
279
- }
280
- return false;
281
- } else {
282
- throw new TypeError(
283
- `The extension in ${extensionPath} is neither a valid ${DRIVER_TYPE} nor a valid ${PLUGIN_TYPE}.`
284
- );
285
- }
286
- }
287
-
288
- /**
289
- * Adds an extension to the manifest as was installed by the `appium` CLI. The
290
- * `extData`, `extType`, and `extName` have already been determined.
291
- *
292
- * See {@link Manifest.addExtensionFromPackage} for adding an extension from an on-disk package.
293
- * @template {ExtensionType} ExtType
294
- * @param {ExtType} extType - `driver` or `plugin`
295
- * @param {string} extName - Name of extension
296
- * @param {ExtManifest<ExtType>} extData - Extension metadata
297
- * @returns {ExtManifest<ExtType>} A clone of `extData`, potentially with a mutated `appiumVersion` field
298
- */
299
- setExtension(extType, extName, extData) {
300
- const data = _.cloneDeep(extData);
301
- this.#data[`${extType}s`][extName] = data;
302
- return data;
303
- }
304
-
305
- /**
306
- * Sets the schema revision
307
- * @param {keyof import('./manifest-migrations').ManifestDataVersions} rev
308
- */
309
- setSchemaRev(rev) {
310
- this.#data.schemaRev = rev;
311
- }
312
-
313
- /**
314
- * Remove an extension from the manifest.
315
- * @param {ExtensionType} extType
316
- * @param {string} extName
317
- */
318
- deleteExtension(extType, extName) {
319
- delete this.#data[`${extType}s`][extName];
320
- }
321
-
322
- /**
323
- * Returns the `APPIUM_HOME` path
324
- */
325
- get appiumHome() {
326
- return this.#appiumHome;
327
- }
328
-
329
- /**
330
- * Returns the path to the manifest file (`extensions.yaml`)
331
- */
332
- get manifestPath() {
333
- return this.#manifestPath;
334
- }
335
-
336
- /**
337
- * Returns the schema rev of this manifest
338
- */
339
- get schemaRev() {
340
- return this.#data.schemaRev;
341
- }
342
-
343
- /**
344
- * Returns extension data for a particular type.
345
- *
346
- * @template {ExtensionType} ExtType
347
- * @param {ExtType} extType
348
- * @returns {Readonly<ExtRecord<ExtType>>}
349
- */
350
- getExtensionData(extType) {
351
- return this.#data[/** @type {string} */ (`${extType}s`)];
352
- }
353
-
354
- /**
355
- * Reads manifest from disk and _overwrites_ the internal data.
356
- *
357
- * If the manifest does not exist on disk, an
358
- * {@link INITIAL_MANIFEST_DATA "empty"} manifest file will be created, as
359
- * well as its directory if needed.
360
- *
361
- * This will also, if necessary:
362
- * 1. perform a migration of the manifest data
363
- * 2. sync the manifest with extensions on-disk (kind of like "auto
364
- * discovery")
365
- * 3. write the manifest to disk.
366
- *
367
- * Only one read operation can happen at a time.
368
- *
369
- * @returns {Promise<ManifestData>} The data
370
- */
371
- async read() {
372
- if (this.#reading) {
373
- await this.#reading;
374
- return this.#data;
375
- }
376
-
377
- this.#reading = (async () => {
378
- /** @type {ManifestData} */
379
- let data;
380
- /**
381
- * This will be `true` if, after reading, we need to update the manifest data
382
- * and write it again to disk.
383
- */
384
- let shouldWrite = false;
385
- await this.#setManifestPath();
386
- try {
387
- const yaml = await fs.readFile(this.#manifestPath, 'utf8');
388
- data = YAML.parse(yaml);
389
- } catch (err) {
390
- if (err.code === 'ENOENT') {
391
- data = _.cloneDeep(INITIAL_MANIFEST_DATA);
392
- shouldWrite = true;
393
- } else if (this.#manifestPath) {
394
- throw new Error(
395
- `Appium had trouble loading the extension installation ` +
396
- `cache file (${this.#manifestPath}). It may be invalid YAML. Specific error: ${
397
- err.message
398
- }`
399
- );
400
- } else {
401
- throw new Error(
402
- `Appium encountered an unknown problem. Specific error: ${err.message}`
403
- );
404
- }
405
- }
406
-
407
- this.#data = data;
408
-
409
- /**
410
- * the only way `shouldWrite` is `true` is if we have a new file. a new
411
- * file will get the latest schema revision, so we can skip the migration.
412
- */
413
- if (!shouldWrite && (data.schemaRev ?? 0) < CURRENT_SCHEMA_REV) {
414
- shouldWrite = await migrate(this);
415
- }
416
-
417
- const hasAppiumDependency = await env.hasAppiumDependency(this.appiumHome);
418
-
419
- /**
420
- * we still may want to sync with installed extensions even if we have a
421
- * new file. right now this is limited to the following cases:
422
- * 1. we have a brand new manifest file
423
- * 2. we have performed a migration on a manifest file
424
- * 3. `appium` is a dependency within `package.json`, and `package.json`
425
- * has changed since last time we checked.
426
- *
427
- * It may also make sense to sync with the extensions in an arbitrary
428
- * `APPIUM_HOME`, but we don't do that here.
429
- */
430
- if (shouldWrite || (hasAppiumDependency && (await packageDidChange(this.appiumHome)))) {
431
- shouldWrite = (await this.syncWithInstalledExtensions(hasAppiumDependency)) || shouldWrite;
432
- }
433
-
434
- if (shouldWrite) {
435
- await this.write();
436
- }
437
- })();
438
-
439
- try {
440
- await this.#reading;
441
- return this.#data;
442
- } finally {
443
- this.#reading = undefined;
444
- }
445
- }
446
-
447
- /**
448
- * Ensures the internal manifest path is set.
449
- *
450
- * Creates the directory if necessary.
451
- * @returns {Promise<string>}
452
- */
453
- async #setManifestPath() {
454
- if (!this.#manifestPath) {
455
- this.#manifestPath = await env.resolveManifestPath(this.#appiumHome);
456
-
457
- /* istanbul ignore if */
458
- if (path.relative(this.#appiumHome, this.#manifestPath).startsWith('.')) {
459
- throw new Error(
460
- `Mismatch between location of APPIUM_HOME and manifest file. APPIUM_HOME: ${
461
- this.appiumHome
462
- }, manifest file: ${this.#manifestPath}`
463
- );
464
- }
465
- }
466
-
467
- return this.#manifestPath;
468
- }
469
-
470
- /**
471
- * Writes the data if it need s writing.
472
- *
473
- * If the `schemaRev` prop needs updating, the file will be written.
474
- *
475
- * @todo If this becomes too much of a bottleneck, throttle it.
476
- * @returns {Promise<boolean>} Whether the data was written
477
- */
478
- async write() {
479
- if (this.#writing) {
480
- return this.#writing;
481
- }
482
- this.#writing = (async () => {
483
- await this.#setManifestPath();
484
- try {
485
- await fs.mkdirp(path.dirname(this.#manifestPath));
486
- } catch (err) {
487
- throw new Error(
488
- `Appium could not create the directory for the manifest file: ${path.dirname(
489
- this.#manifestPath
490
- )}. Original error: ${err.message}`
491
- );
492
- }
493
- try {
494
- await fs.writeFile(this.#manifestPath, YAML.stringify(this.#data), 'utf8');
495
- return true;
496
- } catch (err) {
497
- throw new Error(
498
- `Appium could not write to manifest at ${this.#manifestPath} using APPIUM_HOME ${
499
- this.#appiumHome
500
- }. Please ensure it is writable. Original error: ${err.message}`
501
- );
502
- }
503
- })();
504
- try {
505
- return await this.#writing;
506
- } finally {
507
- this.#writing = undefined;
508
- }
509
- }
510
- }
511
-
512
- /**
513
- * Type of the string referring to a driver (typically as a key or type string)
514
- * @typedef {import('@appium/types').DriverType} DriverType
515
- */
516
-
517
- /**
518
- * Type of the string referring to a plugin (typically as a key or type string)
519
- * @typedef {import('@appium/types').PluginType} PluginType
520
- */
521
-
522
- /**
523
- * @typedef SyncWithInstalledExtensionsOpts
524
- * @property {number} [depthLimit] - Maximum depth to recurse into subdirectories
525
- */
526
-
527
- /**
528
- * @typedef {import('appium/types').ManifestData} ManifestData
529
- * @typedef {import('appium/types').InternalMetadata} InternalMetadata
530
- */
531
-
532
- /**
533
- * @template {ExtensionType} ExtType
534
- * @typedef {import('appium/types').ExtPackageJson<ExtType>} ExtPackageJson
535
- */
536
-
537
- /**
538
- * @template {ExtensionType} ExtType
539
- * @typedef {import('appium/types').ExtManifest<ExtType>} ExtManifest
540
- */
541
-
542
- /**
543
- * @template {ExtensionType} ExtType
544
- * @typedef {import('appium/types').ExtRecord<ExtType>} ExtRecord
545
- */
546
-
547
- /**
548
- * Either `driver` or `plugin` rn
549
- * @typedef {import('@appium/types').ExtensionType} ExtensionType
550
- */
@@ -1,112 +0,0 @@
1
- import _ from 'lodash';
2
- import {ExtensionConfig} from './extension-config';
3
- import log from '../logger';
4
- import {PLUGIN_TYPE} from '../constants';
5
-
6
- /**
7
- * @extends {ExtensionConfig<PluginType>}
8
- */
9
- export class PluginConfig extends ExtensionConfig {
10
- /**
11
- * A mapping of {@link Manifest} instances to {@link PluginConfig} instances.
12
- *
13
- * `Manifest` and {@link ExtensionConfig} have a one-to-many relationship; each `Manifest` should be associated with a `DriverConfig` and a `PluginConfig`; no more, no less.
14
- *
15
- * This variable tracks the `Manifest`-to-`PluginConfig` portion.
16
- *
17
- * @type {WeakMap<Manifest,PluginConfig>}
18
- * @private
19
- */
20
- static _instances = new WeakMap();
21
-
22
- /**
23
- * Call {@link PluginConfig.create} instead.
24
- *
25
- * Just calls the superclass' constructor with the correct extension type
26
- * @private
27
- * @param {Manifest} manifest - IO object
28
- */
29
- constructor(manifest) {
30
- super(PLUGIN_TYPE, manifest);
31
- }
32
-
33
- async validate() {
34
- return await super._validate(this.manifest.getExtensionData(PLUGIN_TYPE));
35
- }
36
-
37
- /**
38
- * Creates a new {@link PluginConfig} instance for a {@link Manifest} instance.
39
- *
40
- * @param {Manifest} manifest
41
- * @throws If `manifest` already associated with a `PluginConfig`
42
- * @returns {PluginConfig}
43
- */
44
- static create(manifest) {
45
- const instance = new PluginConfig(manifest);
46
- if (PluginConfig.getInstance(manifest)) {
47
- throw new Error(
48
- `Manifest with APPIUM_HOME ${manifest.appiumHome} already has a PluginConfig; use PluginConfig.getInstance() to retrieve it.`
49
- );
50
- }
51
- PluginConfig._instances.set(manifest, instance);
52
- return instance;
53
- }
54
-
55
- /**
56
- * Returns a PluginConfig associated with a Manifest
57
- * @param {Manifest} manifest
58
- * @returns {PluginConfig|undefined}
59
- */
60
- static getInstance(manifest) {
61
- return PluginConfig._instances.get(manifest);
62
- }
63
-
64
- /**
65
- * @param {string} pluginName
66
- * @param {import('appium/types').ExtManifest<PluginType>} pluginData
67
- * @returns {string}
68
- */
69
- extensionDesc(pluginName, {version}) {
70
- return `${pluginName}@${version}`;
71
- }
72
-
73
- /**
74
- *
75
- * @param {(keyof import('appium/types').ExtRecord<PluginType>)[]} activeNames
76
- * @returns {void}
77
- */
78
- print(activeNames) {
79
- const pluginNames = Object.keys(this.installedExtensions);
80
-
81
- if (_.isEmpty(pluginNames)) {
82
- log.info(
83
- `No plugins have been installed. Use the "appium plugin" ` +
84
- 'command to install the one(s) you want to use.'
85
- );
86
- return;
87
- }
88
-
89
- log.info(`Available plugins:`);
90
- for (const [pluginName, pluginData] of _.toPairs(this.installedExtensions)) {
91
- const activeTxt = _.includes(activeNames, pluginName) ? ' (ACTIVE)' : '';
92
- log.info(` - ${this.extensionDesc(pluginName, pluginData)}${activeTxt}`);
93
- }
94
-
95
- if (_.isEmpty(activeNames)) {
96
- log.info(
97
- 'No plugins activated. Use the --use-plugins flag with names of plugins to activate'
98
- );
99
- }
100
- }
101
- }
102
-
103
- /**
104
- * @typedef PluginConfigOptions
105
- * @property {import('./extension-config').ExtensionLogFn} [logFn] - Optional logging function
106
- */
107
-
108
- /**
109
- * @typedef {import('@appium/types').PluginType} PluginType
110
- * @typedef {import('appium/types').ExtMetadata<PluginType>} PluginMetadata
111
- * @typedef {import('./manifest').Manifest} Manifest
112
- */