appium 2.0.0-beta.46 → 2.0.0-beta.48

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 (141) hide show
  1. package/README.md +145 -44
  2. package/build/lib/appium.d.ts +3 -103
  3. package/build/lib/appium.d.ts.map +1 -1
  4. package/build/lib/appium.js +679 -549
  5. package/build/lib/appium.js.map +1 -1
  6. package/build/lib/cli/args.js +247 -127
  7. package/build/lib/cli/args.js.map +1 -1
  8. package/build/lib/cli/driver-command.d.ts +24 -5
  9. package/build/lib/cli/driver-command.d.ts.map +1 -1
  10. package/build/lib/cli/driver-command.js +78 -88
  11. package/build/lib/cli/driver-command.js.map +1 -1
  12. package/build/lib/cli/extension-command.d.ts +33 -24
  13. package/build/lib/cli/extension-command.d.ts.map +1 -1
  14. package/build/lib/cli/extension-command.js +729 -512
  15. package/build/lib/cli/extension-command.js.map +1 -1
  16. package/build/lib/cli/extension.d.ts +7 -6
  17. package/build/lib/cli/extension.d.ts.map +1 -1
  18. package/build/lib/cli/extension.js +68 -65
  19. package/build/lib/cli/extension.js.map +1 -1
  20. package/build/lib/cli/parser.d.ts +3 -3
  21. package/build/lib/cli/parser.d.ts.map +1 -1
  22. package/build/lib/cli/parser.js +234 -192
  23. package/build/lib/cli/parser.js.map +1 -1
  24. package/build/lib/cli/plugin-command.js +58 -87
  25. package/build/lib/cli/plugin-command.js.map +1 -1
  26. package/build/lib/cli/utils.js +66 -69
  27. package/build/lib/cli/utils.js.map +1 -1
  28. package/build/lib/config-file.d.ts.map +1 -1
  29. package/build/lib/config-file.js +189 -120
  30. package/build/lib/config-file.js.map +1 -1
  31. package/build/lib/config.d.ts.map +1 -1
  32. package/build/lib/config.js +254 -213
  33. package/build/lib/config.js.map +1 -1
  34. package/build/lib/constants.d.ts +6 -5
  35. package/build/lib/constants.d.ts.map +1 -1
  36. package/build/lib/constants.js +65 -59
  37. package/build/lib/constants.js.map +1 -1
  38. package/build/lib/extension/driver-config.js +199 -164
  39. package/build/lib/extension/driver-config.js.map +1 -1
  40. package/build/lib/extension/extension-config.d.ts +33 -26
  41. package/build/lib/extension/extension-config.d.ts.map +1 -1
  42. package/build/lib/extension/extension-config.js +541 -396
  43. package/build/lib/extension/extension-config.js.map +1 -1
  44. package/build/lib/extension/index.js +98 -68
  45. package/build/lib/extension/index.js.map +1 -1
  46. package/build/lib/extension/manifest-migrations.d.ts +27 -0
  47. package/build/lib/extension/manifest-migrations.d.ts.map +1 -0
  48. package/build/lib/extension/manifest-migrations.js +118 -0
  49. package/build/lib/extension/manifest-migrations.js.map +1 -0
  50. package/build/lib/extension/manifest.d.ts +35 -63
  51. package/build/lib/extension/manifest.d.ts.map +1 -1
  52. package/build/lib/extension/manifest.js +500 -240
  53. package/build/lib/extension/manifest.js.map +1 -1
  54. package/build/lib/extension/package-changed.js +57 -61
  55. package/build/lib/extension/package-changed.js.map +1 -1
  56. package/build/lib/extension/plugin-config.d.ts +2 -3
  57. package/build/lib/extension/plugin-config.d.ts.map +1 -1
  58. package/build/lib/extension/plugin-config.js +94 -70
  59. package/build/lib/extension/plugin-config.js.map +1 -1
  60. package/build/lib/grid-register.js +119 -137
  61. package/build/lib/grid-register.js.map +1 -1
  62. package/build/lib/logger.d.ts +1 -1
  63. package/build/lib/logger.d.ts.map +1 -1
  64. package/build/lib/logger.js +5 -15
  65. package/build/lib/logger.js.map +1 -1
  66. package/build/lib/logsink.d.ts.map +1 -1
  67. package/build/lib/logsink.js +189 -183
  68. package/build/lib/logsink.js.map +1 -1
  69. package/build/lib/main.d.ts +19 -12
  70. package/build/lib/main.d.ts.map +1 -1
  71. package/build/lib/main.js +330 -304
  72. package/build/lib/main.js.map +1 -1
  73. package/build/lib/schema/arg-spec.js +153 -108
  74. package/build/lib/schema/arg-spec.js.map +1 -1
  75. package/build/lib/schema/cli-args.js +203 -164
  76. package/build/lib/schema/cli-args.js.map +1 -1
  77. package/build/lib/schema/cli-transformers.js +117 -72
  78. package/build/lib/schema/cli-transformers.js.map +1 -1
  79. package/build/lib/schema/index.js +17 -32
  80. package/build/lib/schema/index.js.map +1 -1
  81. package/build/lib/schema/keywords.js +125 -67
  82. package/build/lib/schema/keywords.js.map +1 -1
  83. package/build/lib/schema/schema.d.ts.map +1 -1
  84. package/build/lib/schema/schema.js +582 -417
  85. package/build/lib/schema/schema.js.map +1 -1
  86. package/build/lib/utils.d.ts +41 -255
  87. package/build/lib/utils.d.ts.map +1 -1
  88. package/build/lib/utils.js +342 -193
  89. package/build/lib/utils.js.map +1 -1
  90. package/build/tsconfig.tsbuildinfo +1 -1
  91. package/build/types/cli.d.ts +45 -34
  92. package/build/types/cli.d.ts.map +1 -1
  93. package/build/types/cli.js +3 -0
  94. package/build/types/cli.js.map +1 -0
  95. package/build/types/index.d.ts +1 -2
  96. package/build/types/index.d.ts.map +1 -1
  97. package/build/types/index.js +19 -0
  98. package/build/types/index.js.map +1 -0
  99. package/build/types/manifest/base.d.ts +135 -0
  100. package/build/types/manifest/base.d.ts.map +1 -0
  101. package/build/types/manifest/base.js +3 -0
  102. package/build/types/manifest/base.js.map +1 -0
  103. package/build/types/manifest/index.d.ts +19 -0
  104. package/build/types/manifest/index.d.ts.map +1 -0
  105. package/build/types/manifest/index.js +40 -0
  106. package/build/types/manifest/index.js.map +1 -0
  107. package/build/types/manifest/v3.d.ts +139 -0
  108. package/build/types/manifest/v3.d.ts.map +1 -0
  109. package/build/types/manifest/v3.js +3 -0
  110. package/build/types/manifest/v3.js.map +1 -0
  111. package/lib/appium.js +1 -1
  112. package/lib/cli/args.js +1 -1
  113. package/lib/cli/driver-command.js +17 -0
  114. package/lib/cli/extension-command.js +119 -65
  115. package/lib/cli/extension.js +9 -8
  116. package/lib/cli/parser.js +2 -2
  117. package/lib/config-file.js +2 -3
  118. package/lib/config.js +3 -2
  119. package/lib/constants.js +7 -5
  120. package/lib/extension/extension-config.js +52 -47
  121. package/lib/extension/manifest-migrations.js +120 -0
  122. package/lib/extension/manifest.js +184 -103
  123. package/lib/extension/plugin-config.js +1 -2
  124. package/lib/logsink.js +26 -5
  125. package/lib/main.js +58 -50
  126. package/lib/schema/schema.js +6 -1
  127. package/lib/utils.js +62 -0
  128. package/package.json +24 -25
  129. package/scripts/autoinstall-extensions.js +78 -26
  130. package/types/cli.ts +81 -42
  131. package/types/index.ts +1 -2
  132. package/types/manifest/README.md +30 -0
  133. package/types/manifest/base.ts +158 -0
  134. package/types/manifest/index.ts +27 -0
  135. package/types/manifest/v3.ts +161 -0
  136. package/build/types/appium-manifest.d.ts +0 -59
  137. package/build/types/appium-manifest.d.ts.map +0 -1
  138. package/build/types/extension-manifest.d.ts +0 -55
  139. package/build/types/extension-manifest.d.ts.map +0 -1
  140. package/types/appium-manifest.ts +0 -73
  141. package/types/extension-manifest.ts +0 -64
@@ -18,6 +18,16 @@ const UPDATE_ALL = 'installed';
18
18
  class NotUpdatableError extends Error {}
19
19
  class NoUpdatesAvailableError extends Error {}
20
20
 
21
+ /**
22
+ * Omits `driverName`/`pluginName` props from the receipt to make a {@linkcode ExtManifest}
23
+ * @template {ExtensionType} ExtType
24
+ * @param {ExtInstallReceipt<ExtType>} receipt
25
+ * @returns {ExtManifest<ExtType>}
26
+ */
27
+ function receiptToManifest(receipt) {
28
+ return /** @type {ExtManifest<ExtType>} */ (_.omit(receipt, 'driverName', 'pluginName'));
29
+ }
30
+
21
31
  /**
22
32
  * @template {ExtensionType} ExtType
23
33
  */
@@ -128,10 +138,14 @@ class ExtensionCommand {
128
138
  // also don't need to check for updates on non-npm exts
129
139
  continue;
130
140
  }
131
- const updates = await this.checkForExtensionUpdate(ext);
132
- data.updateVersion = updates.safeUpdate;
133
- data.unsafeUpdateVersion = updates.unsafeUpdate;
134
- data.upToDate = updates.safeUpdate === null && updates.unsafeUpdate === null;
141
+ try {
142
+ const updates = await this.checkForExtensionUpdate(ext);
143
+ data.updateVersion = updates.safeUpdate;
144
+ data.unsafeUpdateVersion = updates.unsafeUpdate;
145
+ data.upToDate = updates.safeUpdate === null && updates.unsafeUpdate === null;
146
+ } catch (e) {
147
+ data.updateError = e.message;
148
+ }
135
149
  }
136
150
  });
137
151
 
@@ -149,8 +163,15 @@ class ExtensionCommand {
149
163
  let upToDateTxt = '';
150
164
  let unsafeUpdateTxt = '';
151
165
  if (data.installed) {
152
- const {installType, installSpec, updateVersion, unsafeUpdateVersion, version, upToDate} =
153
- data;
166
+ const {
167
+ installType,
168
+ installSpec,
169
+ updateVersion,
170
+ unsafeUpdateVersion,
171
+ version,
172
+ upToDate,
173
+ updateError,
174
+ } = data;
154
175
  let typeTxt;
155
176
  switch (installType) {
156
177
  case INSTALL_TYPE_GIT:
@@ -166,14 +187,18 @@ class ExtensionCommand {
166
187
  installTxt = `@${version.yellow} ${('[installed ' + typeTxt + ']').green}`;
167
188
 
168
189
  if (showUpdates) {
169
- if (updateVersion) {
170
- updateTxt = ` [${updateVersion} available]`.magenta;
171
- }
172
- if (upToDate) {
173
- upToDateTxt = ` [Up to date]`.green;
174
- }
175
- if (unsafeUpdateVersion) {
176
- unsafeUpdateTxt = ` [${unsafeUpdateVersion} available (potentially unsafe)]`.cyan;
190
+ if (updateError) {
191
+ updateTxt = ` [Cannot check for updates: ${updateError}]`.red;
192
+ } else {
193
+ if (updateVersion) {
194
+ updateTxt = ` [${updateVersion} available]`.magenta;
195
+ }
196
+ if (upToDate) {
197
+ upToDateTxt = ` [Up to date]`.green;
198
+ }
199
+ if (unsafeUpdateVersion) {
200
+ unsafeUpdateTxt = ` [${unsafeUpdateVersion} available (potentially unsafe)]`.cyan;
201
+ }
177
202
  }
178
203
  }
179
204
  }
@@ -187,12 +212,12 @@ class ExtensionCommand {
187
212
  /**
188
213
  * Install an extension
189
214
  *
190
- * @param {InstallArgs} args
215
+ * @param {InstallOpts} opts
191
216
  * @return {Promise<ExtRecord<ExtType>>} map of all installed extension names to extension data
192
217
  */
193
218
  async _install({installSpec, installType, packageName}) {
194
- /** @type {ExtensionFields<ExtType>} */
195
- let extData;
219
+ /** @type {ExtInstallReceipt<ExtType>} */
220
+ let receipt;
196
221
 
197
222
  if (packageName && [INSTALL_TYPE_LOCAL, INSTALL_TYPE_NPM].includes(installType)) {
198
223
  throw this._createFatalError(`When using --source=${installType}, cannot also use --package`);
@@ -205,7 +230,7 @@ class ExtensionCommand {
205
230
  /**
206
231
  * @type {InstallViaNpmArgs}
207
232
  */
208
- let installOpts;
233
+ let installViaNpmOpts;
209
234
 
210
235
  /**
211
236
  * The probable (?) name of the extension derived from the install spec.
@@ -223,8 +248,9 @@ class ExtensionCommand {
223
248
  'it should be of the form <org>/<repo>'
224
249
  );
225
250
  }
226
- installOpts = {
251
+ installViaNpmOpts = {
227
252
  installSpec,
253
+ installType,
228
254
  pkgName: /** @type {string} */ (packageName),
229
255
  };
230
256
  probableExtName = installSpec;
@@ -232,8 +258,9 @@ class ExtensionCommand {
232
258
  // git urls can have '.git' at the end, but this is not necessary and would complicate the
233
259
  // way we download and name directories, so we can just remove it
234
260
  installSpec = installSpec.replace(/\.git$/, '');
235
- installOpts = {
261
+ installViaNpmOpts = {
236
262
  installSpec,
263
+ installType,
237
264
  pkgName: /** @type {string} */ (packageName),
238
265
  };
239
266
  probableExtName = installSpec;
@@ -279,7 +306,7 @@ class ExtensionCommand {
279
306
  installType = INSTALL_TYPE_NPM;
280
307
  }
281
308
  }
282
- installOpts = {installSpec, pkgName, pkgVer};
309
+ installViaNpmOpts = {installSpec, pkgName, pkgVer, installType};
283
310
  }
284
311
 
285
312
  // fail fast here if we can
@@ -291,11 +318,12 @@ class ExtensionCommand {
291
318
  );
292
319
  }
293
320
 
294
- extData = await this.installViaNpm(installOpts);
321
+ receipt = await this.installViaNpm(installViaNpmOpts);
295
322
 
296
323
  // this _should_ be the same as `probablyExtName` as the one derived above unless
297
324
  // install type is local.
298
- const extName = extData[/** @type {string} */ (`${this.type}Name`)];
325
+ /** @type {string} */
326
+ const extName = receipt[/** @type {string} */ (`${this.type}Name`)];
299
327
 
300
328
  // check _a second time_ with the more-accurate extName
301
329
  if (this.config.isInstalled(extName)) {
@@ -308,10 +336,9 @@ class ExtensionCommand {
308
336
 
309
337
  // this field does not exist as such in the manifest (it's used as a property name instead)
310
338
  // so that's why it's being removed here.
311
- delete extData[/** @type {string} */ (`${this.type}Name`)];
312
-
313
339
  /** @type {ExtManifest<ExtType>} */
314
- const extManifest = {...extData, installType, installSpec};
340
+ const extManifest = receiptToManifest(receipt);
341
+
315
342
  const [errors, warnings] = await B.all([
316
343
  this.config.getProblems(extName, extManifest),
317
344
  this.config.getWarnings(extName, extManifest),
@@ -334,13 +361,13 @@ class ExtensionCommand {
334
361
 
335
362
  await this.config.addExtension(extName, extManifest);
336
363
 
337
- // update the if we've changed the local `package.json`
364
+ // update the hash if we've changed the local `package.json`
338
365
  if (await env.hasAppiumDependency(this.config.appiumHome)) {
339
366
  await packageDidChange(this.config.appiumHome);
340
367
  }
341
368
 
342
369
  // log info for the user
343
- this.log.info(this.getPostInstallText({extName, extData}));
370
+ this.log.info(this.getPostInstallText({extName, extData: receipt}));
344
371
 
345
372
  return this.config.installedExtensions;
346
373
  }
@@ -349,21 +376,28 @@ class ExtensionCommand {
349
376
  * Install an extension via NPM
350
377
  *
351
378
  * @param {InstallViaNpmArgs} args
379
+ * @returns {Promise<ExtInstallReceipt<ExtType>>}
352
380
  */
353
- async installViaNpm({installSpec, pkgName, pkgVer}) {
381
+ async installViaNpm({installSpec, pkgName, pkgVer, installType}) {
354
382
  const npmSpec = `${pkgName}${pkgVer ? '@' + pkgVer : ''}`;
355
383
  const specMsg = npmSpec === installSpec ? '' : ` using NPM install spec '${npmSpec}'`;
356
384
  const msg = `Installing '${installSpec}'${specMsg}`;
357
385
  try {
358
- const pkgJsonData = await spinWith(this.isJsonOutput, msg, async () => {
359
- const pkgJsonData = await npm.installPackage(this.config.appiumHome, pkgName, {
386
+ const {pkg, path} = await spinWith(this.isJsonOutput, msg, async () => {
387
+ const {pkg, installPath: path} = await npm.installPackage(this.config.appiumHome, pkgName, {
360
388
  pkgVer,
389
+ installType,
361
390
  });
362
- this.validatePackageJson(pkgJsonData, installSpec);
363
- return pkgJsonData;
391
+ this.validatePackageJson(pkg, installSpec);
392
+ return {pkg, path};
364
393
  });
365
394
 
366
- return this.getExtensionFields(pkgJsonData);
395
+ return this.getInstallationReceipt({
396
+ pkg,
397
+ installPath: path,
398
+ installType,
399
+ installSpec,
400
+ });
367
401
  } catch (err) {
368
402
  throw this._createFatalError(`Encountered an error when installing package: ${err.message}`);
369
403
  }
@@ -382,25 +416,31 @@ class ExtensionCommand {
382
416
  }
383
417
 
384
418
  /**
385
- * Take an NPM module's package.json and extract Appium driver information from a special
386
- * 'appium' field in the JSON data. We need this information to e.g. determine which class to
387
- * load as the main driver class, or to be able to detect incompatibilities between driver and
388
- * appium versions.
419
+ * Once a package is installed on-disk, this gathers some necessary metadata for validation.
389
420
  *
390
- * @param {ExtPackageJson<ExtType>} pkgJson - the package.json data for a driver module, as if it had been straightforwardly 'require'd
391
- * @returns {ExtensionFields<ExtType>}
421
+ * @param {GetInstallationReceiptOpts<ExtType>} opts
422
+ * @returns {ExtInstallReceipt<ExtType>}
392
423
  */
393
- getExtensionFields(pkgJson) {
394
- const {appium, name, version, peerDependencies} = pkgJson;
424
+ getInstallationReceipt({pkg, installPath, installType, installSpec}) {
425
+ const {appium, name, version, peerDependencies} = pkg;
395
426
 
396
- /** @type {unknown} */
397
- const result = {
398
- ...appium,
427
+ /** @type {import('appium/types').InternalMetadata} */
428
+ const internal = {
399
429
  pkgName: name,
400
430
  version,
431
+ installType,
432
+ installSpec,
433
+ installPath,
401
434
  appiumVersion: peerDependencies?.appium,
402
435
  };
403
- return /** @type {ExtensionFields<ExtType>} */ (result);
436
+
437
+ /** @type {ExtMetadata<ExtType>} */
438
+ const extMetadata = appium;
439
+
440
+ return {
441
+ ...internal,
442
+ ...extMetadata,
443
+ };
404
444
  }
405
445
 
406
446
  /**
@@ -410,13 +450,13 @@ class ExtensionCommand {
410
450
  * - `name`
411
451
  * - `version`
412
452
  * - `appium`
413
- * @param {import('type-fest').PackageJson} pkgJson - `package.json` of extension
453
+ * @param {import('type-fest').PackageJson} pkg - `package.json` of extension
414
454
  * @param {string} installSpec - Extension name/spec
415
455
  * @throws {ReferenceError} If `package.json` has a missing or invalid field
416
- * @returns {pkgJson is ExtPackageJson<ExtType>}
456
+ * @returns {pkg is ExtPackageJson<ExtType>}
417
457
  */
418
- validatePackageJson(pkgJson, installSpec) {
419
- const {appium, name, version} = /** @type {ExtPackageJson<ExtType>} */ (pkgJson);
458
+ validatePackageJson(pkg, installSpec) {
459
+ const {appium, name, version} = /** @type {ExtPackageJson<ExtType>} */ (pkg);
420
460
 
421
461
  /**
422
462
  *
@@ -608,9 +648,10 @@ class ExtensionCommand {
608
648
  * @returns {Promise<void>}
609
649
  */
610
650
  async updateExtension(installSpec, version) {
611
- const {pkgName} = this.config.installedExtensions[installSpec];
651
+ const {pkgName, installType} = this.config.installedExtensions[installSpec];
612
652
  const extData = await this.installViaNpm({
613
653
  installSpec,
654
+ installType,
614
655
  pkgName,
615
656
  pkgVer: version,
616
657
  });
@@ -637,7 +678,7 @@ class ExtensionCommand {
637
678
  const extConfig = this.config.installedExtensions[installSpec];
638
679
 
639
680
  // note: TS cannot understand that _.has() is a type guard
640
- if (!extConfig.scripts) {
681
+ if (!('scripts' in extConfig)) {
641
682
  throw this._createFatalError(
642
683
  `The ${this.type} named '${installSpec}' does not contain the ` +
643
684
  `"scripts" field underneath the "appium" field in its package.json`
@@ -646,13 +687,13 @@ class ExtensionCommand {
646
687
 
647
688
  const extScripts = extConfig.scripts;
648
689
 
649
- if (!_.isPlainObject(extScripts)) {
690
+ if (!extScripts || !_.isPlainObject(extScripts)) {
650
691
  throw this._createFatalError(
651
692
  `The ${this.type} named '${installSpec}' "scripts" field must be a plain object`
652
693
  );
653
694
  }
654
695
 
655
- if (!_.has(extScripts, scriptName)) {
696
+ if (!(scriptName in extScripts)) {
656
697
  throw this._createFatalError(
657
698
  `The ${this.type} named '${installSpec}' does not support the script: '${scriptName}'`
658
699
  );
@@ -701,6 +742,7 @@ export {ExtensionCommand};
701
742
  * @property {string?} updateVersion - If the extension is installed, the version it can be updated to
702
743
  * @property {string?} unsafeUpdateVersion - Same as above, but a major version bump
703
744
  * @property {boolean} upToDate - If the extension is installed and the latest
745
+ * @property {string?} updateError - Update check error message (if present)
704
746
  */
705
747
 
706
748
  /**
@@ -734,11 +776,14 @@ export {ExtensionCommand};
734
776
  * @typedef {import('appium/types').ExtPackageJson<ExtType>} ExtPackageJson
735
777
  */
736
778
 
779
+ /**
780
+ * @template {ExtensionType} ExtType
781
+ * @typedef {import('appium/types').ExtInstallReceipt<ExtType>} ExtInstallReceipt
782
+ */
783
+
737
784
  /**
738
785
  * Possible return value for {@linkcode ExtensionCommand.list}
739
- * @typedef UninstalledExtensionListData
740
- * @property {string} pkgName
741
- * @property {false} installed
786
+ * @typedef {Partial<InstalledExtensionListData> & {pkgName: string, installed: false}} UninstalledExtensionListData
742
787
  */
743
788
 
744
789
  /**
@@ -806,6 +851,7 @@ export {ExtensionCommand};
806
851
  * @typedef InstallViaNpmArgs
807
852
  * @property {string} installSpec - the name or spec of an extension to install
808
853
  * @property {string} pkgName - the NPM package name of the extension
854
+ * @property {import('appium/types').InstallType} installType - type of install
809
855
  * @property {string} [pkgVer] - the specific version of the NPM package
810
856
  */
811
857
 
@@ -819,18 +865,12 @@ export {ExtensionCommand};
819
865
 
820
866
  /**
821
867
  * Options for {@linkcode ExtensionCommand._install}
822
- * @typedef InstallArgs
868
+ * @typedef InstallOpts
823
869
  * @property {string} installSpec - the name or spec of an extension to install
824
- * @property {import('appium/types').InstallType} installType - how to install this extension. One of the INSTALL_TYPES
870
+ * @property {InstallType} installType - how to install this extension. One of the INSTALL_TYPES
825
871
  * @property {string} [packageName] - for git/github installs, the extension node package name
826
872
  */
827
873
 
828
- /**
829
- * Returned by {@linkcode ExtensionCommand.getExtensionFields}
830
- * @template {ExtensionType} ExtType
831
- * @typedef {ExtMetadata<ExtType> & { pkgName: string, version: string, appiumVersion: string } & import('appium/types').CommonExtMetadata} ExtensionFields
832
- */
833
-
834
874
  /**
835
875
  * @template {ExtensionType} ExtType
836
876
  * @typedef {ExtType extends DriverType ? typeof import('../constants').KNOWN_DRIVERS : ExtType extends PluginType ? typeof import('../constants').KNOWN_PLUGINS : never} KnownExtensions
@@ -841,3 +881,17 @@ export {ExtensionCommand};
841
881
  * @property {boolean} showInstalled - whether should show only installed extensions
842
882
  * @property {boolean} showUpdates - whether should show available updates
843
883
  */
884
+
885
+ /**
886
+ * Opts for {@linkcode ExtensionCommand.getInstallationReceipt}
887
+ * @template {ExtensionType} ExtType
888
+ * @typedef GetInstallationReceiptOpts
889
+ * @property {string} installPath
890
+ * @property {string} installSpec
891
+ * @property {ExtPackageJson<ExtType>} pkg
892
+ * @property {InstallType} installType
893
+ */
894
+
895
+ /**
896
+ * @typedef {import('appium/types').InstallType} InstallType
897
+ */
@@ -1,7 +1,8 @@
1
1
  /* eslint-disable no-console */
2
+ import {DRIVER_TYPE, PLUGIN_TYPE} from '../constants';
3
+ import {isExtensionCommandArgs} from '../utils';
2
4
  import DriverCommand from './driver-command';
3
5
  import PluginCommand from './plugin-command';
4
- import {DRIVER_TYPE, PLUGIN_TYPE} from '../constants';
5
6
  import {errAndQuit, JSON_SPACES} from './utils';
6
7
 
7
8
  export const commandClasses = Object.freeze(
@@ -15,18 +16,18 @@ export const commandClasses = Object.freeze(
15
16
  * Run a subcommand of the 'appium driver' type. Each subcommand has its own set of arguments which
16
17
  * can be represented as a JS object.
17
18
  *
18
- * @param {import('appium/types').Args<import('appium/types').WithExtSubcommand>} args - JS object where the key is the parameter name (as defined in
19
+ * @template {import('appium/types').CliExtensionCommand} Cmd
20
+ * @template {import('appium/types').CliExtensionSubcommand} SubCmd
21
+ * @param {import('appium/types').Args<Cmd, SubCmd>} args - JS object where the key is the parameter name (as defined in
19
22
  * driver-parser.js)
20
- * @template {ExtensionType} ExtType
21
- * @param {import('../extension/extension-config').ExtensionConfig<ExtType>} config - Extension config object
23
+ * @param {import('../extension/extension-config').ExtensionConfig<Cmd>} config - Extension config object
22
24
  */
23
25
  async function runExtensionCommand(args, config) {
24
26
  // TODO driver config file should be locked while any of these commands are
25
27
  // running to prevent weird situations
26
28
  let jsonResult = null;
27
- const {extensionType: type} = config;
28
- const extCmd = args[`${type}Command`];
29
- if (!extCmd) {
29
+ const {extensionType: type} = config; // NOTE this is the same as `args.subcommand`
30
+ if (!isExtensionCommandArgs(args)) {
30
31
  throw new TypeError(`Cannot call ${type} command without a subcommand like 'install'`);
31
32
  }
32
33
  let {json, suppressOutput} = args;
@@ -34,7 +35,7 @@ async function runExtensionCommand(args, config) {
34
35
  if (suppressOutput) {
35
36
  json = true;
36
37
  }
37
- const CommandClass = /** @type {ExtCommand<ExtType>} */ (commandClasses[type]);
38
+ const CommandClass = /** @type {ExtCommand<Cmd>} */ (commandClasses[type]);
38
39
  const cmd = new CommandClass({config, json});
39
40
  try {
40
41
  jsonResult = await cmd.execute(args);
package/lib/cli/parser.js CHANGED
@@ -89,9 +89,9 @@ class ArgParser {
89
89
  * If no subcommand is passed in, this method will inject the `server` subcommand.
90
90
  *
91
91
  * `ArgParser.prototype.parse_args` is an alias of this method.
92
- * @template [T=import('appium/types').WithServerSubcommand]
92
+ * @template {import('appium/types').CliCommand} [Cmd=import('appium/types').ServerCommand]
93
93
  * @param {string[]} [args] - Array of arguments, ostensibly from `process.argv`. Gathers args from `process.argv` if not provided.
94
- * @returns {import('appium/types').Args<T>} - The parsed arguments
94
+ * @returns {import('appium/types').Args<Cmd>} - The parsed arguments
95
95
  */
96
96
  parseArgs(args = process.argv.slice(2)) {
97
97
  if (!NON_SERVER_ARGS.has(args[0])) {
@@ -154,9 +154,8 @@ export function normalizeConfig(config) {
154
154
  const normalize = (config, section) => {
155
155
  const obj = _.isUndefined(section) ? config : _.get(config, section, config);
156
156
 
157
- const mappedObj = _.mapKeys(
158
- obj,
159
- (__, prop) => schema.properties[prop]?.appiumCliDest ?? _.camelCase(prop)
157
+ const mappedObj = _.mapKeys(obj, (__, prop) =>
158
+ _.get(schema, `properties.server.properties[${prop}].appiumCliDest`, _.camelCase(prop))
160
159
  );
161
160
 
162
161
  return _.mapValues(mappedObj, (value, property) => {
package/lib/config.js CHANGED
@@ -298,11 +298,12 @@ function showConfig(nonDefaultPreConfigParsedArgs, configResult, defaults, parse
298
298
  } else {
299
299
  console.log(`\n(no configuration file loaded)`);
300
300
  }
301
- if (_.isEmpty(nonDefaultPreConfigParsedArgs)) {
301
+ const compactedNonDefaultPreConfigArgs = compactConfig(nonDefaultPreConfigParsedArgs);
302
+ if (_.isEmpty(compactedNonDefaultPreConfigArgs)) {
302
303
  console.log(`\n(no CLI parameters provided)`);
303
304
  } else {
304
305
  console.log('\nvia CLI or function call:\n');
305
- console.dir(compactConfig(nonDefaultPreConfigParsedArgs));
306
+ console.dir(compactedNonDefaultPreConfigArgs);
306
307
  }
307
308
  console.log('\nfinal configuration:\n');
308
309
  console.dir(compactConfig(parsedArgs));
package/lib/constants.js CHANGED
@@ -29,6 +29,7 @@ export const KNOWN_PLUGINS = Object.freeze(
29
29
  images: '@appium/images-plugin',
30
30
  'execute-driver': '@appium/execute-driver-plugin',
31
31
  'relaxed-caps': '@appium/relaxed-caps-plugin',
32
+ 'universal-xml': '@appium/universal-xml-plugin',
32
33
  })
33
34
  );
34
35
 
@@ -40,15 +41,11 @@ export const KNOWN_DRIVERS = Object.freeze(
40
41
  /** @type {const} */ ({
41
42
  uiautomator2: 'appium-uiautomator2-driver',
42
43
  xcuitest: 'appium-xcuitest-driver',
43
- youiengine: 'appium-youiengine-driver',
44
- windows: 'appium-windows-driver',
45
- mac: 'appium-mac-driver',
46
44
  mac2: 'appium-mac2-driver',
47
45
  espresso: 'appium-espresso-driver',
48
- tizen: 'appium-tizen-driver',
49
- flutter: 'appium-flutter-driver',
50
46
  safari: 'appium-safari-driver',
51
47
  gecko: 'appium-geckodriver',
48
+ chromium: 'appium-chromium-driver',
52
49
  })
53
50
  );
54
51
 
@@ -67,3 +64,8 @@ export const EXT_SUBCOMMAND_INSTALL = 'install';
67
64
  export const EXT_SUBCOMMAND_UNINSTALL = 'uninstall';
68
65
  export const EXT_SUBCOMMAND_UPDATE = 'update';
69
66
  export const EXT_SUBCOMMAND_RUN = 'run';
67
+
68
+ /**
69
+ * Current revision of the manifest (`extensions.yaml`) schema
70
+ */
71
+ export const CURRENT_SCHEMA_REV = 3;