appium 2.0.0-beta.25 → 2.0.0-beta.28

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 (191) hide show
  1. package/build/lib/appium.d.ts +215 -0
  2. package/build/lib/appium.d.ts.map +1 -0
  3. package/build/lib/appium.js +94 -101
  4. package/build/lib/cli/args.d.ts +20 -0
  5. package/build/lib/cli/args.d.ts.map +1 -0
  6. package/build/lib/cli/args.js +19 -39
  7. package/build/lib/cli/driver-command.d.ts +36 -0
  8. package/build/lib/cli/driver-command.d.ts.map +1 -0
  9. package/build/lib/cli/driver-command.js +10 -13
  10. package/build/lib/cli/extension-command.d.ts +345 -0
  11. package/build/lib/cli/extension-command.d.ts.map +1 -0
  12. package/build/lib/cli/extension-command.js +117 -94
  13. package/build/lib/cli/extension.d.ts +14 -0
  14. package/build/lib/cli/extension.d.ts.map +1 -0
  15. package/build/lib/cli/extension.js +14 -22
  16. package/build/lib/cli/parser.d.ts +79 -0
  17. package/build/lib/cli/parser.d.ts.map +1 -0
  18. package/build/lib/cli/parser.js +9 -19
  19. package/build/lib/cli/plugin-command.d.ts +39 -0
  20. package/build/lib/cli/plugin-command.d.ts.map +1 -0
  21. package/build/lib/cli/plugin-command.js +9 -14
  22. package/build/lib/cli/utils.d.ts +29 -0
  23. package/build/lib/cli/utils.d.ts.map +1 -0
  24. package/build/lib/cli/utils.js +2 -4
  25. package/build/lib/config-file.d.ts +100 -0
  26. package/build/lib/config-file.d.ts.map +1 -0
  27. package/build/lib/config-file.js +2 -4
  28. package/build/lib/config.d.ts +40 -0
  29. package/build/lib/config.d.ts.map +1 -0
  30. package/build/lib/config.js +8 -7
  31. package/build/lib/constants.d.ts +48 -0
  32. package/build/lib/constants.d.ts.map +1 -0
  33. package/build/lib/constants.js +60 -0
  34. package/build/lib/extension/driver-config.d.ts +84 -0
  35. package/build/lib/extension/driver-config.d.ts.map +1 -0
  36. package/build/lib/extension/driver-config.js +190 -0
  37. package/build/lib/extension/extension-config.d.ts +170 -0
  38. package/build/lib/extension/extension-config.d.ts.map +1 -0
  39. package/build/lib/extension/extension-config.js +297 -0
  40. package/build/lib/extension/index.d.ts +39 -0
  41. package/build/lib/extension/index.d.ts.map +1 -0
  42. package/build/lib/extension/index.js +77 -0
  43. package/build/lib/extension/manifest.d.ts +174 -0
  44. package/build/lib/extension/manifest.d.ts.map +1 -0
  45. package/build/lib/extension/manifest.js +246 -0
  46. package/build/lib/extension/package-changed.d.ts +11 -0
  47. package/build/lib/extension/package-changed.d.ts.map +1 -0
  48. package/build/lib/extension/package-changed.js +68 -0
  49. package/build/lib/extension/plugin-config.d.ts +62 -0
  50. package/build/lib/extension/plugin-config.d.ts.map +1 -0
  51. package/build/lib/extension/plugin-config.js +87 -0
  52. package/build/lib/grid-register.d.ts +10 -0
  53. package/build/lib/grid-register.d.ts.map +1 -0
  54. package/build/lib/grid-register.js +2 -4
  55. package/build/lib/logger.d.ts +3 -0
  56. package/build/lib/logger.d.ts.map +1 -0
  57. package/build/lib/logger.js +2 -4
  58. package/build/lib/logsink.d.ts +4 -0
  59. package/build/lib/logsink.d.ts.map +1 -0
  60. package/build/lib/logsink.js +2 -4
  61. package/build/lib/main.d.ts +51 -0
  62. package/build/lib/main.d.ts.map +1 -0
  63. package/build/lib/main.js +40 -68
  64. package/build/lib/schema/arg-spec.d.ts +143 -0
  65. package/build/lib/schema/arg-spec.d.ts.map +1 -0
  66. package/build/lib/schema/arg-spec.js +11 -14
  67. package/build/lib/schema/cli-args.d.ts +19 -0
  68. package/build/lib/schema/cli-args.d.ts.map +1 -0
  69. package/build/lib/schema/cli-args.js +2 -4
  70. package/build/lib/schema/cli-transformers.d.ts +5 -0
  71. package/build/lib/schema/cli-transformers.d.ts.map +1 -0
  72. package/build/lib/schema/cli-transformers.js +2 -4
  73. package/build/lib/schema/index.d.ts +3 -0
  74. package/build/lib/schema/index.d.ts.map +1 -0
  75. package/build/lib/schema/index.js +2 -4
  76. package/build/lib/schema/keywords.d.ts +24 -0
  77. package/build/lib/schema/keywords.d.ts.map +1 -0
  78. package/build/lib/schema/keywords.js +2 -4
  79. package/build/lib/schema/schema.d.ts +259 -0
  80. package/build/lib/schema/schema.d.ts.map +1 -0
  81. package/build/lib/schema/schema.js +57 -39
  82. package/build/lib/utils.d.ts +66 -0
  83. package/build/lib/utils.d.ts.map +1 -0
  84. package/build/lib/utils.js +6 -35
  85. package/build/tsconfig.tsbuildinfo +1 -0
  86. package/lib/appium.js +188 -117
  87. package/lib/cli/args.js +19 -24
  88. package/lib/cli/driver-command.js +19 -8
  89. package/lib/cli/extension-command.js +314 -184
  90. package/lib/cli/extension.js +18 -16
  91. package/lib/cli/parser.js +7 -16
  92. package/lib/cli/plugin-command.js +16 -7
  93. package/lib/cli/utils.js +1 -1
  94. package/lib/config-file.js +6 -7
  95. package/lib/config.js +17 -12
  96. package/lib/constants.js +78 -0
  97. package/lib/extension/driver-config.js +249 -0
  98. package/lib/extension/extension-config.js +458 -0
  99. package/lib/extension/index.js +102 -0
  100. package/lib/extension/manifest.js +486 -0
  101. package/lib/extension/package-changed.js +63 -0
  102. package/lib/extension/plugin-config.js +113 -0
  103. package/lib/grid-register.js +4 -4
  104. package/lib/logsink.js +4 -0
  105. package/lib/main.js +54 -92
  106. package/lib/schema/arg-spec.js +11 -7
  107. package/lib/schema/cli-args.js +1 -1
  108. package/lib/schema/cli-transformers.js +0 -1
  109. package/lib/schema/keywords.js +1 -2
  110. package/lib/schema/schema.js +62 -31
  111. package/lib/utils.js +48 -45
  112. package/package.json +30 -24
  113. package/{postinstall.js → scripts/postinstall.js} +1 -1
  114. package/types/appium-manifest.d.ts +61 -0
  115. package/types/cli.d.ts +134 -0
  116. package/types/extension.d.ts +56 -0
  117. package/types/external-manifest.d.ts +58 -0
  118. package/types/index.d.ts +7 -0
  119. package/bin/ios-webkit-debug-proxy-launcher.js +0 -71
  120. package/build/check-npm-pack-files.js +0 -23
  121. package/build/commands-yml/parse.js +0 -319
  122. package/build/commands-yml/validator.js +0 -130
  123. package/build/index.js +0 -19
  124. package/build/lib/appium-config.schema.json +0 -0
  125. package/build/lib/cli/npm.js +0 -220
  126. package/build/lib/driver-config.js +0 -100
  127. package/build/lib/drivers.js +0 -100
  128. package/build/lib/ext-config-io.js +0 -165
  129. package/build/lib/extension-config.js +0 -320
  130. package/build/lib/plugin-config.js +0 -69
  131. package/build/lib/plugins.js +0 -18
  132. package/build/lib/schema/appium-config-schema.js +0 -253
  133. package/build/postinstall.js +0 -90
  134. package/build/test/cli/cli-e2e-specs.js +0 -221
  135. package/build/test/cli/cli-helpers.js +0 -86
  136. package/build/test/cli/cli-specs.js +0 -71
  137. package/build/test/cli/fixtures/test-driver/package.json +0 -27
  138. package/build/test/cli/schema-args-specs.js +0 -48
  139. package/build/test/cli/schema-e2e-specs.js +0 -47
  140. package/build/test/config-e2e-specs.js +0 -112
  141. package/build/test/config-file-e2e-specs.js +0 -191
  142. package/build/test/config-file-specs.js +0 -281
  143. package/build/test/config-specs.js +0 -258
  144. package/build/test/driver-e2e-specs.js +0 -435
  145. package/build/test/driver-specs.js +0 -386
  146. package/build/test/ext-config-io-specs.js +0 -181
  147. package/build/test/extension-config-specs.js +0 -365
  148. package/build/test/fixtures/allow-feat.txt +0 -5
  149. package/build/test/fixtures/caps.json +0 -3
  150. package/build/test/fixtures/config/allow-insecure.txt +0 -3
  151. package/build/test/fixtures/config/appium.config.bad-nodeconfig.json +0 -5
  152. package/build/test/fixtures/config/appium.config.bad.json +0 -32
  153. package/build/test/fixtures/config/appium.config.ext-good.json +0 -9
  154. package/build/test/fixtures/config/appium.config.ext-unknown-props.json +0 -10
  155. package/build/test/fixtures/config/appium.config.good.js +0 -40
  156. package/build/test/fixtures/config/appium.config.good.json +0 -33
  157. package/build/test/fixtures/config/appium.config.good.yaml +0 -30
  158. package/build/test/fixtures/config/appium.config.invalid.json +0 -31
  159. package/build/test/fixtures/config/appium.config.security-array.json +0 -5
  160. package/build/test/fixtures/config/appium.config.security-delimited.json +0 -5
  161. package/build/test/fixtures/config/appium.config.security-path.json +0 -5
  162. package/build/test/fixtures/config/driver-fake.config.json +0 -8
  163. package/build/test/fixtures/config/nodeconfig.json +0 -3
  164. package/build/test/fixtures/config/plugin-fake.config.json +0 -0
  165. package/build/test/fixtures/default-args.js +0 -35
  166. package/build/test/fixtures/deny-feat.txt +0 -5
  167. package/build/test/fixtures/driver.schema.js +0 -20
  168. package/build/test/fixtures/extensions.yaml +0 -27
  169. package/build/test/fixtures/flattened-schema.js +0 -532
  170. package/build/test/fixtures/plugin.schema.js +0 -20
  171. package/build/test/fixtures/schema-with-extensions.js +0 -28
  172. package/build/test/grid-register-specs.js +0 -74
  173. package/build/test/helpers.js +0 -75
  174. package/build/test/logger-specs.js +0 -76
  175. package/build/test/npm-specs.js +0 -20
  176. package/build/test/parser-specs.js +0 -319
  177. package/build/test/plugin-e2e-specs.js +0 -316
  178. package/build/test/schema/arg-spec-specs.js +0 -70
  179. package/build/test/schema/cli-args-specs.js +0 -408
  180. package/build/test/schema/schema-specs.js +0 -407
  181. package/build/test/utils-specs.js +0 -288
  182. package/lib/cli/npm.js +0 -251
  183. package/lib/driver-config.js +0 -101
  184. package/lib/drivers.js +0 -84
  185. package/lib/ext-config-io.js +0 -287
  186. package/lib/extension-config.js +0 -366
  187. package/lib/plugin-config.js +0 -63
  188. package/lib/plugins.js +0 -13
  189. package/lib/schema/appium-config-schema.js +0 -287
  190. package/types/appium-config.d.ts +0 -197
  191. package/types/types.d.ts +0 -206
package/lib/main.js CHANGED
@@ -1,26 +1,26 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // transpile:main
4
- // @ts-check
5
3
 
6
- import logger from './logger'; // logger needs to remain first of imports
4
+ import { init as logsinkInit } from './logsink'; // this import needs to come first since it sets up global npmlog
5
+ import logger from './logger'; // logger needs to remain second
7
6
  // @ts-ignore
8
7
  import { routeConfiguringFunction as makeRouter, server as baseServer } from '@appium/base-driver';
9
- import { logger as logFactory, util } from '@appium/support';
8
+ import { logger as logFactory, util, env } from '@appium/support';
10
9
  import { asyncify } from 'asyncbox';
11
10
  import _ from 'lodash';
12
11
  import { AppiumDriver } from './appium';
13
- import { driverConfig, pluginConfig, USE_ALL_PLUGINS } from './cli/args';
14
12
  import { runExtensionCommand } from './cli/extension';
15
- import { default as getParser, SERVER_SUBCOMMAND } from './cli/parser';
16
- import { APPIUM_VER, checkNodeOk, getGitRev, getNonDefaultServerArgs, showBuildInfo, validateTmpDir, warnNodeDeprecations, showConfig } from './config';
13
+ import { getParser } from './cli/parser';
14
+ import { APPIUM_VER, checkNodeOk, getGitRev, getNonDefaultServerArgs, showConfig, showBuildInfo, validateTmpDir, warnNodeDeprecations } from './config';
17
15
  import { readConfigFile } from './config-file';
18
- import { DRIVER_TYPE, PLUGIN_TYPE } from './extension-config';
16
+ import { loadExtensions, getActivePlugins, getActiveDrivers } from './extension';
17
+ import { DRIVER_TYPE, PLUGIN_TYPE, SERVER_SUBCOMMAND } from './constants';
19
18
  import registerNode from './grid-register';
20
- import { init as logsinkInit } from './logsink';
21
- import { getDefaultsForSchema } from './schema/schema';
19
+ import { getDefaultsForSchema, validate } from './schema/schema';
22
20
  import { inspect } from './utils';
23
21
 
22
+ const {resolveAppiumHome} = env;
23
+
24
24
  /**
25
25
  *
26
26
  * @param {ParsedArgs} args
@@ -38,6 +38,8 @@ async function preflightChecks (args, throwInsteadOfExit = false) {
38
38
  }
39
39
  warnNodeDeprecations();
40
40
 
41
+ validate(args);
42
+
41
43
  if (args.tmpDir) {
42
44
  await validateTmpDir(args.tmpDir);
43
45
  }
@@ -102,63 +104,11 @@ function logServerPort (address, port) {
102
104
  logger.info(logMessage);
103
105
  }
104
106
 
105
- /**
106
- * Find any plugin name which has been installed, and which has been requested for activation by
107
- * using the --use-plugins flag, and turn each one into its class, so we can send them as objects
108
- * to the server init. We also want to send/assign them to the umbrella driver so it can use them
109
- * to wrap command execution
110
- *
111
- * @param {Object} args - argparser parsed dict
112
- * @param {import('./plugin-config').default} pluginConfig - a plugin extension config
113
- * @returns {PluginExtensionClass[]}
114
- */
115
- function getActivePlugins (args, pluginConfig) {
116
- return _.compact(Object.keys(pluginConfig.installedExtensions).filter((pluginName) =>
117
- _.includes(args.usePlugins, pluginName) ||
118
- (args.usePlugins.length === 1 && args.usePlugins[0] === USE_ALL_PLUGINS)
119
- ).map((pluginName) => {
120
- try {
121
- logger.info(`Attempting to load plugin ${pluginName}...`);
122
- const PluginClass = /** @type {PluginExtensionClass} */(pluginConfig.require(pluginName));
123
-
124
- PluginClass.pluginName = pluginName; // store the plugin name on the class so it can be used later
125
- return PluginClass;
126
- } catch (err) {
127
- logger.error(`Could not load plugin '${pluginName}', so it will not be available. Error ` +
128
- `in loading the plugin was: ${err.message}`);
129
- logger.debug(err.stack);
130
- }
131
- }));
132
- }
133
-
134
- /**
135
- * Find any driver name which has been installed, and turn each one into its class, so we can send
136
- * them as objects to the server init in case they need to add methods/routes or update the server.
137
- * If the --drivers flag was given, this method only loads the given drivers.
138
- *
139
- * @param {Object} args - argparser parsed dict
140
- * @param {import('./driver-config').default} driverConfig - a driver extension config
141
- */
142
- function getActiveDrivers (args, driverConfig) {
143
- return _.compact(Object.keys(driverConfig.installedExtensions).filter((driverName) =>
144
- _.includes(args.useDrivers, driverName) || args.useDrivers.length === 0
145
- ).map((driverName) => {
146
- try {
147
- logger.info(`Attempting to load driver ${driverName}...`);
148
- return driverConfig.require(driverName);
149
- } catch (err) {
150
- logger.error(`Could not load driver '${driverName}', so it will not be available. Error ` +
151
- `in loading the driver was: ${err.message}`);
152
- logger.debug(err.stack);
153
- }
154
- }));
155
- }
156
-
157
107
  /**
158
108
  * Gets a list of `updateServer` functions from all extensions
159
- * @param {DriverExtensionClass[]} driverClasses
160
- * @param {PluginExtensionClass[]} pluginClasses
161
- * @returns {StaticExtMembers['updateServer'][]}
109
+ * @param {DriverClass[]} driverClasses
110
+ * @param {PluginClass[]} pluginClasses
111
+ * @returns {import('@appium/base-driver/lib/basedriver/driver').UpdateServerCallback[]}
162
112
  */
163
113
  function getServerUpdaters (driverClasses, pluginClasses) {
164
114
  return _.compact(_.map([...driverClasses, ...pluginClasses], 'updateServer'));
@@ -166,9 +116,9 @@ function getServerUpdaters (driverClasses, pluginClasses) {
166
116
 
167
117
  /**
168
118
  * Makes a big `MethodMap` from all the little `MethodMap`s in the extensions
169
- * @param {DriverExtensionClass[]} driverClasses
170
- * @param {PluginExtensionClass[]} pluginClasses
171
- * @returns {import('@appium/base-driver').MethodMap}
119
+ * @param {DriverClass[]} driverClasses
120
+ * @param {PluginClass[]} pluginClasses
121
+ * @returns {import('@appium/types').MethodMap}
172
122
  */
173
123
  function getExtraMethodMap (driverClasses, pluginClasses) {
174
124
  return [...driverClasses, ...pluginClasses].reduce(
@@ -182,11 +132,10 @@ function getExtraMethodMap (driverClasses, pluginClasses) {
182
132
  *
183
133
  * Use this to get at the configuration schema.
184
134
  *
185
- * If `args` contains a non-empty `subcommand` which is not `server`, this function
186
- * will resolve with an empty object.
135
+ * If `args` contains a non-empty `subcommand` which is not `server`, this function will return an empty object.
187
136
  *
188
- * @param {ParsedArgs} [args] - Parsed args
189
- * @returns {Promise<Partial<{appiumDriver: AppiumDriver, parsedArgs: ParsedArgs}>>}
137
+ * @param {PartialArgs} [args] - Partial args (progammatic usage only)
138
+ * @returns {Promise<ServerInitResult | ExtCommandInitResult>}
190
139
  * @example
191
140
  * import {init, getSchema} from 'appium';
192
141
  * const options = {}; // config object
@@ -194,11 +143,15 @@ function getExtraMethodMap (driverClasses, pluginClasses) {
194
143
  * const schema = getSchema(); // entire config schema including plugins and drivers
195
144
  */
196
145
  async function init (args) {
197
- const parser = await getParser();
146
+ const appiumHome = args?.appiumHome ?? await resolveAppiumHome();
147
+
148
+ const {driverConfig, pluginConfig} = await loadExtensions(appiumHome);
149
+
150
+ const parser = getParser();
198
151
  let throwInsteadOfExit = false;
199
152
  /** @type {ParsedArgs} */
200
153
  let preConfigParsedArgs;
201
- /** @type {typeof preConfigParsedArgs & import('type-fest').AsyncReturnType<readConfigFile>['config']} */
154
+ /** @type {ParsedArgs} */
202
155
  let parsedArgs;
203
156
  /**
204
157
  * This is a definition (instead of declaration) because TS can't figure out
@@ -215,7 +168,7 @@ async function init (args) {
215
168
  // but remove it since it's not a real server arg per se
216
169
  delete args.throwInsteadOfExit;
217
170
  }
218
- preConfigParsedArgs = {...args, subcommand: args.subcommand ?? SERVER_SUBCOMMAND};
171
+ preConfigParsedArgs = /** @type {ParsedArgs} */({...args, subcommand: args.subcommand ?? SERVER_SUBCOMMAND});
219
172
  } else {
220
173
  // otherwise parse from CLI
221
174
  preConfigParsedArgs = parser.parseArgs();
@@ -227,7 +180,6 @@ async function init (args) {
227
180
  throw new Error(`Errors in config file ${configResult.filepath}:\n ${configResult.reason ?? configResult.errors}`);
228
181
  }
229
182
 
230
-
231
183
  // merge config and apply defaults.
232
184
  // the order of precendece is:
233
185
  // 1. command line args
@@ -256,11 +208,11 @@ async function init (args) {
256
208
  // if the user has requested the 'driver' CLI, don't run the normal server,
257
209
  // but instead pass control to the driver CLI
258
210
  if (parsedArgs.subcommand === DRIVER_TYPE) {
259
- await runExtensionCommand(parsedArgs, parsedArgs.subcommand, driverConfig);
211
+ await runExtensionCommand(parsedArgs, driverConfig);
260
212
  return {};
261
213
  }
262
214
  if (parsedArgs.subcommand === PLUGIN_TYPE) {
263
- await runExtensionCommand(parsedArgs, parsedArgs.subcommand, pluginConfig);
215
+ await runExtensionCommand(parsedArgs, pluginConfig);
264
216
  return {};
265
217
  }
266
218
 
@@ -282,32 +234,32 @@ async function init (args) {
282
234
  appiumDriver.driverConfig = driverConfig;
283
235
  await preflightChecks(parsedArgs, throwInsteadOfExit);
284
236
 
285
- return {appiumDriver, parsedArgs};
237
+ return /** @type {ServerInitResult} */({appiumDriver, parsedArgs, driverConfig, pluginConfig});
286
238
  }
287
239
 
288
240
  /**
289
241
  * Initializes Appium's config. Starts server if appropriate and resolves the
290
242
  * server instance if so; otherwise resolves w/ `undefined`.
291
- * @param {ParsedArgs} [args] - Arguments from CLI or otherwise
292
- * @returns {Promise<import('express').Express|undefined>}
243
+ * @param {PartialArgs} [args] - Arguments from CLI or otherwise
244
+ * @returns {Promise<import('http').Server|undefined>}
293
245
  */
294
246
  async function main (args) {
295
- const {appiumDriver, parsedArgs} = await init(args);
247
+ const {appiumDriver, parsedArgs, pluginConfig, driverConfig} = /** @type {ServerInitResult} */(await init(args));
296
248
 
297
- if (!appiumDriver || !parsedArgs) {
249
+ if (!appiumDriver || !parsedArgs || !pluginConfig || !driverConfig) {
298
250
  // if this branch is taken, we've run a different subcommand, so there's nothing
299
251
  // left to do here.
300
252
  return;
301
253
  }
302
254
 
303
- const pluginClasses = getActivePlugins(parsedArgs, pluginConfig);
255
+ const pluginClasses = getActivePlugins(pluginConfig, parsedArgs.usePlugins);
304
256
  // set the active plugins on the umbrella driver so it can use them for commands
305
257
  appiumDriver.pluginClasses = pluginClasses;
306
258
 
307
259
  await logStartupInfo(parsedArgs);
308
260
  let routeConfiguringFunction = makeRouter(appiumDriver);
309
261
 
310
- const driverClasses = getActiveDrivers(parsedArgs, driverConfig);
262
+ const driverClasses = getActiveDrivers(driverConfig, parsedArgs.useDrivers);
311
263
  const serverUpdaters = getServerUpdaters(driverClasses, pluginClasses);
312
264
  const extraMethodMap = getExtraMethodMap(driverClasses, pluginClasses);
313
265
 
@@ -382,23 +334,33 @@ if (require.main === module) {
382
334
  }
383
335
 
384
336
  // everything below here is intended to be a public API.
385
- export { main, init };
386
- export { APPIUM_HOME } from './extension-config';
387
- export { getSchema, validate, finalizeSchema } from './schema/schema';
388
337
  export { readConfigFile } from './config-file';
338
+ export { finalizeSchema, getSchema, validate } from './schema/schema';
339
+ export { main, init, resolveAppiumHome };
340
+
341
+ /**
342
+ * @typedef {import('../types/cli').ParsedArgs} ParsedArgs
343
+ */
389
344
 
390
345
  /**
391
- * @typedef {import('../types/types').ParsedArgs} ParsedArgs
346
+ * @typedef {import('../types/cli').PartialArgs} PartialArgs
347
+ * @typedef {import('../types').DriverType} DriverType
348
+ * @typedef {import('../types').PluginType} PluginType
349
+ * @typedef {import('../types/extension').DriverClass} DriverClass
350
+ * @typedef {import('../types/extension').PluginClass} PluginClass
392
351
  */
393
352
 
394
353
  /**
395
- * @typedef {import('./appium').PluginExtensionClass} PluginExtensionClass
354
+ * Literally an empty object
355
+ * @typedef { {} } ExtCommandInitResult
396
356
  */
397
357
 
398
358
  /**
399
- * @typedef {import('./appium').DriverExtensionClass} DriverExtensionClass
359
+ * @typedef ServerInitData
360
+ * @property {AppiumDriver} appiumDriver - The Appium driver
361
+ * @property {ParsedArgs} parsedArgs - The parsed arguments
400
362
  */
401
363
 
402
364
  /**
403
- * @typedef {import('./appium').StaticExtMembers} StaticExtMembers
365
+ * @typedef {ServerInitData & import('./extension').ExtensionConfigs} ServerInitResult
404
366
  */
@@ -28,6 +28,7 @@ const PROPERTIES = 'properties';
28
28
  * option) used for cross-referencing.
29
29
  *
30
30
  * This class has no instance methods, and is basically just a read-only "struct".
31
+ * @template D
31
32
  */
32
33
  export class ArgSpec {
33
34
  /**
@@ -81,7 +82,7 @@ export class ArgSpec {
81
82
  /**
82
83
  * Whatever the default value of this argument is, as specified by the
83
84
  * `default` property of the schema.
84
- * @type {D}
85
+ * @type {D|undefined}
85
86
  */
86
87
  defaultValue;
87
88
 
@@ -92,7 +93,6 @@ export class ArgSpec {
92
93
  *
93
94
  * The _constructor_ is private. Use {@link ArgSpec.create} instead.
94
95
  * @private
95
- * @template D
96
96
  * @param {string} name
97
97
  * @param {ArgSpecOptions<D>} [opts]
98
98
  */
@@ -176,12 +176,15 @@ export class ArgSpec {
176
176
  /**
177
177
  * When given the root ID of a schema for an extension (`<extType>-<normalizedExtName>.json`) Returns an object containing the extension type and the _normalized_ extension name.
178
178
  * @param {string} schemaId - Root schema ID
179
- * @returns { {extType: ExtensionType|undefined, normalizedExtName: string|undefined} }
179
+ * @returns { {extType?: ExtensionType, normalizedExtName?: string} }
180
180
  */
181
181
  static extensionInfoFromRootSchemaId (schemaId) {
182
182
  const matches = schemaId.match(SCHEMA_ID_REGEXP);
183
183
  if (matches?.groups) {
184
- const {extType, normalizedExtName} = matches.groups;
184
+ const {extType, normalizedExtName} =
185
+ /** @type { {extType: ExtensionType, normalizedExtName: string} } */ (
186
+ matches.groups
187
+ );
185
188
  return {extType, normalizedExtName};
186
189
  }
187
190
  return {};
@@ -192,7 +195,8 @@ export class ArgSpec {
192
195
  *
193
196
  * @param {string} name - The canonical name of the argument. Corresponds to a key in a schema's
194
197
  * `properties` property.
195
- * @param {ArgSpecOptions} [opts] - Options
198
+ * @template D
199
+ * @param {ArgSpecOptions<D>} [opts] - Options
196
200
  * @returns {Readonly<ArgSpec>}
197
201
  */
198
202
  static create (name, opts) {
@@ -216,7 +220,7 @@ export class ArgSpec {
216
220
  /**
217
221
  * Options for {@link ArgSpec.create}
218
222
  * @template D
219
- * @typedef {Object} ArgSpecOptions
223
+ * @typedef ArgSpecOptions
220
224
  * @property {string} [extName]
221
225
  * @property {ExtensionType} [extType]
222
226
  * @property {string} [dest]
@@ -224,5 +228,5 @@ export class ArgSpec {
224
228
  */
225
229
 
226
230
  /**
227
- * @typedef {import('../ext-config-io').ExtensionType} ExtensionType
231
+ * @typedef {import('../extension/manifest').ExtensionType} ExtensionType
228
232
  */
@@ -1,4 +1,3 @@
1
- // @ts-check
2
1
 
3
2
  import {ArgumentTypeError} from 'argparse';
4
3
  import _ from 'lodash';
@@ -139,6 +138,7 @@ function subSchemaToArgDef (subSchema, argSpec) {
139
138
  // handle special cases for various types
140
139
  switch (type) {
141
140
  // booleans do not have a type per `ArgumentOptions`, just an "action"
141
+ // NOTE: due to limitations of `argparse`, we cannot provide fancy help text, and must rely on its internal error messaging.
142
142
  case TYPENAMES.BOOLEAN: {
143
143
  argOpts.action = 'store_const';
144
144
  argOpts.const = true;
@@ -1,4 +1,3 @@
1
- // @ts-check
2
1
 
3
2
  import { ArgumentTypeError } from 'argparse';
4
3
  import { readFileSync } from 'fs';
@@ -1,4 +1,3 @@
1
- // @ts-check
2
1
 
3
2
  import { transformers } from './cli-transformers';
4
3
 
@@ -120,7 +119,7 @@ export const keywords = {
120
119
  /**
121
120
  * These are the custom keywords that Appium recognizes.
122
121
  *
123
- * @typedef {Object} AppiumJSONSchemaKeywords
122
+ * @typedef AppiumJSONSchemaKeywords
124
123
  * @property {string} [appiumCliDest]
125
124
  * @property {string} [appiumCliDescription]
126
125
  * @property {string[]} [appiumCliAliases]
@@ -1,15 +1,44 @@
1
- // @ts-check
2
1
 
3
2
  import Ajv from 'ajv';
4
3
  import addFormats from 'ajv-formats';
5
4
  import _ from 'lodash';
6
5
  import path from 'path';
7
- import { DRIVER_TYPE, PLUGIN_TYPE } from '../extension-config';
8
- import { ReadonlyMap } from '../utils';
9
- import appiumConfigSchema from './appium-config-schema';
6
+ import { DRIVER_TYPE, PLUGIN_TYPE } from '../constants';
7
+ import { AppiumConfigJsonSchema } from '@appium/schema';
10
8
  import { APPIUM_CONFIG_SCHEMA_ID, ArgSpec, SERVER_PROP_NAME } from './arg-spec';
11
9
  import { keywords } from './keywords';
12
10
 
11
+ /**
12
+ * Key/value pairs go in... but they don't come out.
13
+ *
14
+ * @template K,V
15
+ * @extends {Map<K,V>}
16
+ */
17
+ export class RoachHotelMap extends Map {
18
+ /**
19
+ * @param {K} key
20
+ * @param {V} value
21
+ */
22
+ set (key, value) {
23
+ if (this.has(key)) {
24
+ throw new Error(`${key} is already set`);
25
+ }
26
+ return super.set(key, value);
27
+ }
28
+
29
+ /**
30
+ * @param {K} key
31
+ */
32
+ // eslint-disable-next-line no-unused-vars
33
+ delete (key) {
34
+ return false;
35
+ }
36
+
37
+ clear () {
38
+ throw new Error(`Cannot clear RoachHotelMap`);
39
+ }
40
+ }
41
+
13
42
  /**
14
43
  * Extensions that an extension schema file can have.
15
44
  */
@@ -28,9 +57,9 @@ class AppiumSchema {
28
57
  *
29
58
  * Used to provide easy lookups of argument metadata when converting between different representations of those arguments.
30
59
  * @private
31
- * @type {ReadonlyMap<string,ArgSpec>}
60
+ * @type {RoachHotelMap<string,ArgSpec>}
32
61
  */
33
- _argSpecs = new ReadonlyMap();
62
+ _argSpecs = new RoachHotelMap();
34
63
 
35
64
  /**
36
65
  * A map of extension types to extension names to schema objects.
@@ -83,25 +112,27 @@ class AppiumSchema {
83
112
  * @returns {AppiumSchema}
84
113
  */
85
114
  static create () {
86
- const instance = AppiumSchema._instance ?? new AppiumSchema();
87
- AppiumSchema._instance = instance;
88
-
89
- _.bindAll(instance, [
90
- 'finalize',
91
- 'flatten',
92
- 'getAllArgSpecs',
93
- 'getArgSpec',
94
- 'getDefaults',
95
- 'getDefaultsForExtension',
96
- 'getSchema',
97
- 'hasArgSpec',
98
- 'isFinalized',
99
- 'registerSchema',
100
- 'reset',
101
- 'validate',
102
- ]);
103
-
104
- return instance;
115
+ if (!AppiumSchema._instance) {
116
+ const instance = new AppiumSchema();
117
+ AppiumSchema._instance = instance;
118
+ _.bindAll(instance, [
119
+ 'finalize',
120
+ 'flatten',
121
+ 'getAllArgSpecs',
122
+ 'getArgSpec',
123
+ 'getDefaults',
124
+ 'getDefaultsForExtension',
125
+ 'getSchema',
126
+ 'hasArgSpec',
127
+ 'isFinalized',
128
+ 'registerSchema',
129
+ 'hasRegisteredSchema',
130
+ 'reset',
131
+ 'validate',
132
+ ]);
133
+ }
134
+
135
+ return AppiumSchema._instance;
105
136
  }
106
137
 
107
138
  /**
@@ -150,7 +181,7 @@ class AppiumSchema {
150
181
  */
151
182
  finalize () {
152
183
  if (this.isFinalized()) {
153
- return /** @type {Record<string,StrictSchemaObject>} */ (
184
+ return /** @type {NonNullable<typeof this._finalizedSchemas>} */ (
154
185
  this._finalizedSchemas
155
186
  );
156
187
  }
@@ -158,7 +189,7 @@ class AppiumSchema {
158
189
  const ajv = this._ajv;
159
190
 
160
191
  // Ajv will _mutate_ the schema, so we need to clone it.
161
- const baseSchema = _.cloneDeep(appiumConfigSchema);
192
+ const baseSchema = _.cloneDeep(AppiumConfigJsonSchema);
162
193
 
163
194
  /**
164
195
  *
@@ -259,7 +290,7 @@ class AppiumSchema {
259
290
  for (const schemaId of Object.keys(this._finalizedSchemas ?? {})) {
260
291
  this._ajv.removeSchema(schemaId);
261
292
  }
262
- this._argSpecs = new ReadonlyMap();
293
+ this._argSpecs = new RoachHotelMap();
263
294
  this._registeredSchemas = {
264
295
  [DRIVER_TYPE]: new Map(),
265
296
  [PLUGIN_TYPE]: new Map(),
@@ -276,7 +307,7 @@ class AppiumSchema {
276
307
  * This is "fail-fast" in that the schema will immediately be validated against JSON schema draft-07 _or_ whatever the value of the schema's `$schema` prop is.
277
308
  *
278
309
  * Does _not_ add the schema to the `ajv` instance (this is done by {@link AppiumSchema.finalize}).
279
- * @param {import('../ext-config-io').ExtensionType} extType - Extension type
310
+ * @param {ExtensionType} extType - Extension type
280
311
  * @param {string} extName - Unique extension name for `type`
281
312
  * @param {SchemaObject} schema - Schema object
282
313
  * @throws {SchemaNameConflictError} If the schema is an invalid
@@ -666,12 +697,12 @@ export const {isAllowedSchemaFileExtension} = AppiumSchema;
666
697
  */
667
698
 
668
699
  /**
669
- * @typedef {import('../ext-config-io').ExtensionType} ExtensionType
700
+ * @typedef {import('../extension/manifest').ExtensionType} ExtensionType
670
701
  */
671
702
 
672
703
  /**
673
704
  * An object having property `additionalProperties: false`
674
- * @typedef {Object} StrictProp
705
+ * @typedef StrictProp
675
706
  * @property {false} additionalProperties
676
707
  */
677
708