appium 2.0.0-beta.30 → 2.0.0-beta.35

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 (69) hide show
  1. package/build/lib/appium.d.ts +1 -1
  2. package/build/lib/appium.d.ts.map +1 -1
  3. package/build/lib/appium.js +5 -2
  4. package/build/lib/cli/args.js +1 -1
  5. package/build/lib/cli/driver-command.d.ts +3 -3
  6. package/build/lib/cli/driver-command.d.ts.map +1 -1
  7. package/build/lib/cli/driver-command.js +8 -8
  8. package/build/lib/cli/extension-command.d.ts +22 -17
  9. package/build/lib/cli/extension-command.d.ts.map +1 -1
  10. package/build/lib/cli/extension-command.js +35 -36
  11. package/build/lib/cli/extension.js +1 -1
  12. package/build/lib/cli/parser.d.ts +3 -2
  13. package/build/lib/cli/parser.d.ts.map +1 -1
  14. package/build/lib/cli/parser.js +1 -1
  15. package/build/lib/cli/plugin-command.d.ts +9 -15
  16. package/build/lib/cli/plugin-command.d.ts.map +1 -1
  17. package/build/lib/cli/plugin-command.js +8 -8
  18. package/build/lib/cli/utils.js +1 -1
  19. package/build/lib/config-file.js +1 -1
  20. package/build/lib/config.d.ts +5 -4
  21. package/build/lib/config.d.ts.map +1 -1
  22. package/build/lib/config.js +1 -1
  23. package/build/lib/constants.js +1 -1
  24. package/build/lib/extension/driver-config.js +1 -1
  25. package/build/lib/extension/extension-config.js +1 -1
  26. package/build/lib/extension/index.js +1 -1
  27. package/build/lib/extension/manifest.d.ts.map +1 -1
  28. package/build/lib/extension/manifest.js +1 -1
  29. package/build/lib/extension/package-changed.js +1 -1
  30. package/build/lib/extension/plugin-config.js +1 -1
  31. package/build/lib/grid-register.js +1 -1
  32. package/build/lib/logger.js +1 -1
  33. package/build/lib/logsink.js +1 -1
  34. package/build/lib/main.d.ts +13 -10
  35. package/build/lib/main.d.ts.map +1 -1
  36. package/build/lib/main.js +57 -50
  37. package/build/lib/schema/arg-spec.js +1 -1
  38. package/build/lib/schema/cli-args.js +1 -1
  39. package/build/lib/schema/cli-transformers.js +1 -1
  40. package/build/lib/schema/index.js +1 -1
  41. package/build/lib/schema/keywords.js +1 -1
  42. package/build/lib/schema/schema.js +1 -1
  43. package/build/lib/utils.js +1 -1
  44. package/build/tsconfig.tsbuildinfo +1 -1
  45. package/build/types/appium-manifest.d.ts +40 -0
  46. package/build/types/appium-manifest.d.ts.map +1 -0
  47. package/build/types/cli.d.ts +112 -0
  48. package/build/types/cli.d.ts.map +1 -0
  49. package/build/types/extension.d.ts +43 -0
  50. package/build/types/extension.d.ts.map +1 -0
  51. package/build/types/external-manifest.d.ts +47 -0
  52. package/build/types/external-manifest.d.ts.map +1 -0
  53. package/build/types/index.d.ts +15 -0
  54. package/build/types/index.d.ts.map +1 -0
  55. package/lib/appium.js +7 -3
  56. package/lib/cli/driver-command.js +45 -20
  57. package/lib/cli/extension-command.js +229 -123
  58. package/lib/cli/parser.js +2 -1
  59. package/lib/cli/plugin-command.js +33 -18
  60. package/lib/config.js +6 -5
  61. package/lib/extension/manifest.js +0 -2
  62. package/lib/main.js +78 -63
  63. package/package.json +20 -14
  64. package/types/{appium-manifest.d.ts → appium-manifest.ts} +1 -1
  65. package/types/{cli.d.ts → cli.ts} +48 -29
  66. package/types/{extension.d.ts → extension.ts} +4 -4
  67. package/types/{external-manifest.d.ts → external-manifest.ts} +2 -2
  68. package/types/{index.d.ts → index.ts} +7 -0
  69. package/lib/appium-config.schema.json +0 -278
@@ -2,12 +2,16 @@
2
2
 
3
3
  import _ from 'lodash';
4
4
  import path from 'path';
5
- import { npm, fs, util, env } from '@appium/support';
6
- import { log, spinWith, RingBuffer } from './utils';
7
- import { SubProcess } from 'teen_process';
8
- import { INSTALL_TYPE_NPM, INSTALL_TYPE_GIT, INSTALL_TYPE_GITHUB,
9
- INSTALL_TYPE_LOCAL } from '../extension/extension-config';
10
- import { packageDidChange } from '../extension/package-changed';
5
+ import {npm, fs, util, env} from '@appium/support';
6
+ import {log, spinWith, RingBuffer} from './utils';
7
+ import {SubProcess} from 'teen_process';
8
+ import {
9
+ INSTALL_TYPE_NPM,
10
+ INSTALL_TYPE_GIT,
11
+ INSTALL_TYPE_GITHUB,
12
+ INSTALL_TYPE_LOCAL,
13
+ } from '../extension/extension-config';
14
+ import {packageDidChange} from '../extension/package-changed';
11
15
 
12
16
  const UPDATE_ALL = 'installed';
13
17
 
@@ -80,24 +84,31 @@ class ExtensionCommand {
80
84
  * @return {Promise<ExtensionListData>} map of extension names to extension data
81
85
  */
82
86
  async list ({showInstalled, showUpdates}) {
83
- const lsMsg = `Listing ${showInstalled ? 'installed' : 'available'} ${this.type}s`;
87
+ const lsMsg = `Listing ${showInstalled ? 'installed' : 'available'} ${
88
+ this.type
89
+ }s`;
84
90
  const installedNames = Object.keys(this.config.installedExtensions);
85
91
  const knownNames = Object.keys(this.knownExtensions);
86
- const exts = [...installedNames, ...knownNames].reduce((acc, name) => {
87
- if (!acc[name]) {
88
- if (installedNames.includes(name)) {
89
- acc[name] = {...this.config.installedExtensions[name], installed: true};
90
- } else if (!showInstalled) {
91
- acc[name] = {pkgName: this.knownExtensions[name], installed: false};
92
+ const exts = [...installedNames, ...knownNames].reduce(
93
+ (acc, name) => {
94
+ if (!acc[name]) {
95
+ if (installedNames.includes(name)) {
96
+ acc[name] = {
97
+ ...this.config.installedExtensions[name],
98
+ installed: true,
99
+ };
100
+ } else if (!showInstalled) {
101
+ acc[name] = {pkgName: this.knownExtensions[name], installed: false};
102
+ }
92
103
  }
93
- }
94
- return acc;
95
- },
96
- /**
97
- * This accumulator contains either {@linkcode UninstalledExtensionLIstData} _or_
98
- * {@linkcode InstalledExtensionListData} without upgrade information (which is added by the below code block)
99
- * @type {Record<string,Partial<InstalledExtensionListData>|UninstalledExtensionListData>}
100
- */({}));
104
+ return acc;
105
+ },
106
+ /**
107
+ * This accumulator contains either {@linkcode UninstalledExtensionLIstData} _or_
108
+ * {@linkcode InstalledExtensionListData} without upgrade information (which is added by the below code block)
109
+ * @type {Record<string,Partial<InstalledExtensionListData>|UninstalledExtensionListData>}
110
+ */ ({})
111
+ );
101
112
 
102
113
  // if we want to show whether updates are available, put that behind a spinner
103
114
  await spinWith(this.isJsonOutput, lsMsg, async () => {
@@ -113,11 +124,12 @@ class ExtensionCommand {
113
124
  const updates = await this.checkForExtensionUpdate(ext);
114
125
  data.updateVersion = updates.safeUpdate;
115
126
  data.unsafeUpdateVersion = updates.unsafeUpdate;
116
- data.upToDate = updates.safeUpdate === null && updates.unsafeUpdate === null;
127
+ data.upToDate =
128
+ updates.safeUpdate === null && updates.unsafeUpdate === null;
117
129
  }
118
130
  });
119
131
 
120
- const listData = /** @type {ExtensionListData} */(exts);
132
+ const listData = /** @type {ExtensionListData} */ (exts);
121
133
 
122
134
  // if we're just getting the data, short circuit return here since we don't need to do any
123
135
  // formatting logic
@@ -125,16 +137,20 @@ class ExtensionCommand {
125
137
  return listData;
126
138
  }
127
139
 
128
- for (const [
129
- name,
130
- data
131
- ] of _.toPairs(listData)) {
140
+ for (const [name, data] of _.toPairs(listData)) {
132
141
  let installTxt = ' [not installed]'.grey;
133
142
  let updateTxt = '';
134
143
  let upToDateTxt = '';
135
144
  let unsafeUpdateTxt = '';
136
145
  if (data.installed) {
137
- const {installType, installSpec, updateVersion, unsafeUpdateVersion, version, upToDate} = data;
146
+ const {
147
+ installType,
148
+ installSpec,
149
+ updateVersion,
150
+ unsafeUpdateVersion,
151
+ version,
152
+ upToDate,
153
+ } = data;
138
154
  let typeTxt;
139
155
  switch (installType) {
140
156
  case INSTALL_TYPE_GIT:
@@ -147,7 +163,9 @@ class ExtensionCommand {
147
163
  default:
148
164
  typeTxt = '(NPM)';
149
165
  }
150
- installTxt = `@${version.yellow} ${('[installed ' + typeTxt + ']').green}`;
166
+ installTxt = `@${version.yellow} ${
167
+ ('[installed ' + typeTxt + ']').green
168
+ }`;
151
169
 
152
170
  if (showUpdates) {
153
171
  if (updateVersion) {
@@ -157,12 +175,15 @@ class ExtensionCommand {
157
175
  upToDateTxt = ` [Up to date]`.green;
158
176
  }
159
177
  if (unsafeUpdateVersion) {
160
- unsafeUpdateTxt = ` [${unsafeUpdateVersion} available (potentially unsafe)]`.cyan;
178
+ unsafeUpdateTxt =
179
+ ` [${unsafeUpdateVersion} available (potentially unsafe)]`.cyan;
161
180
  }
162
181
  }
163
182
  }
164
183
 
165
- console.log(`- ${name.yellow}${installTxt}${updateTxt}${upToDateTxt}${unsafeUpdateTxt}`);
184
+ console.log(
185
+ `- ${name.yellow}${installTxt}${updateTxt}${upToDateTxt}${unsafeUpdateTxt}`
186
+ );
166
187
  }
167
188
 
168
189
  return listData;
@@ -174,33 +195,53 @@ class ExtensionCommand {
174
195
  * @param {InstallArgs} args
175
196
  * @return {Promise<ExtRecord<ExtType>>} map of all installed extension names to extension data
176
197
  */
177
- async _install ({ext, installType, packageName}) {
198
+ async _install ({installSpec, installType, packageName}) {
199
+ /** @type {ExtensionFields<typeof this.type>} */
178
200
  let extData;
179
- let installSpec = ext;
180
201
 
181
- if (packageName && [INSTALL_TYPE_LOCAL, INSTALL_TYPE_NPM].includes(installType)) {
182
- throw new Error(`When using --source=${installType}, cannot also use --package`);
202
+ if (
203
+ packageName &&
204
+ [INSTALL_TYPE_LOCAL, INSTALL_TYPE_NPM].includes(installType)
205
+ ) {
206
+ throw new Error(
207
+ `When using --source=${installType}, cannot also use --package`
208
+ );
183
209
  }
184
210
 
185
- if (!packageName && [INSTALL_TYPE_GIT, INSTALL_TYPE_GITHUB].includes(installType)) {
186
- throw new Error(`When using --source=${installType}, must also use --package`);
211
+ if (
212
+ !packageName &&
213
+ [INSTALL_TYPE_GIT, INSTALL_TYPE_GITHUB].includes(installType)
214
+ ) {
215
+ throw new Error(
216
+ `When using --source=${installType}, must also use --package`
217
+ );
187
218
  }
188
219
 
189
220
  if (installType === INSTALL_TYPE_GITHUB) {
190
221
  if (installSpec.split('/').length !== 2) {
191
- throw new Error(`Github ${this.type} spec ${installSpec} appeared to be invalid; ` +
192
- 'it should be of the form <org>/<repo>');
222
+ throw new Error(
223
+ `Github ${this.type} spec ${installSpec} appeared to be invalid; ` +
224
+ 'it should be of the form <org>/<repo>'
225
+ );
193
226
  }
194
- extData = await this.installViaNpm({ext: installSpec, pkgName: /** @type {string} */(packageName)});
227
+ extData = await this.installViaNpm({
228
+ installSpec,
229
+ pkgName: /** @type {string} */ (packageName),
230
+ });
195
231
  } else if (installType === INSTALL_TYPE_GIT) {
196
232
  // git urls can have '.git' at the end, but this is not necessary and would complicate the
197
233
  // way we download and name directories, so we can just remove it
198
234
  installSpec = installSpec.replace(/\.git$/, '');
199
- extData = await this.installViaNpm({ext: installSpec, pkgName: /** @type {string} */(packageName)});
235
+ extData = await this.installViaNpm({
236
+ installSpec,
237
+ pkgName: /** @type {string} */ (packageName),
238
+ });
200
239
  } else {
201
240
  let pkgName, pkgVer;
202
241
  if (installType === INSTALL_TYPE_LOCAL) {
203
- pkgName = path.isAbsolute(installSpec) ? installSpec : path.resolve(installSpec);
242
+ pkgName = path.isAbsolute(installSpec)
243
+ ? installSpec
244
+ : path.resolve(installSpec);
204
245
  } else {
205
246
  // at this point we have either an npm package or an appium verified extension
206
247
  // name or a local path. both of which will be installed via npm.
@@ -227,8 +268,9 @@ class ExtensionCommand {
227
268
  // check it exists and get the correct package
228
269
  const knownNames = Object.keys(this.knownExtensions);
229
270
  if (!_.includes(knownNames, name)) {
230
- const msg = `Could not resolve ${this.type}; are you sure it's in the list ` +
231
- `of supported ${this.type}s? ${JSON.stringify(knownNames)}`;
271
+ const msg =
272
+ `Could not resolve ${this.type}; are you sure it's in the list ` +
273
+ `of supported ${this.type}s? ${JSON.stringify(knownNames)}`;
232
274
  throw new Error(msg);
233
275
  }
234
276
  pkgName = this.knownExtensions[name];
@@ -238,16 +280,18 @@ class ExtensionCommand {
238
280
  }
239
281
  }
240
282
 
241
- extData = await this.installViaNpm({ext, pkgName, pkgVer});
283
+ extData = await this.installViaNpm({installSpec, pkgName, pkgVer});
242
284
  }
243
285
 
244
- const extName = extData[/** @type {string} */(`${this.type}Name`)];
245
- delete extData[/** @type {string} */(`${this.type}Name`)];
286
+ const extName = extData[/** @type {string} */ (`${this.type}Name`)];
287
+ delete extData[/** @type {string} */ (`${this.type}Name`)];
246
288
 
247
289
  if (this.config.isInstalled(extName)) {
248
- throw new Error(`A ${this.type} named '${extName}' is already installed. ` +
249
- `Did you mean to update? 'appium ${this.type} update'. See ` +
250
- `installed ${this.type}s with 'appium ${this.type} list --installed'.`);
290
+ throw new Error(
291
+ `A ${this.type} named '${extName}' is already installed. ` +
292
+ `Did you mean to update? 'appium ${this.type} update'. See ` +
293
+ `installed ${this.type}s with 'appium ${this.type} list --installed'.`
294
+ );
251
295
  }
252
296
 
253
297
  const extManifest = {...extData, installType, installSpec};
@@ -269,19 +313,25 @@ class ExtensionCommand {
269
313
  *
270
314
  * @param {InstallViaNpmArgs} args
271
315
  */
272
- async installViaNpm ({ext, pkgName, pkgVer}) {
316
+ async installViaNpm ({installSpec, pkgName, pkgVer}) {
273
317
  const npmSpec = `${pkgName}${pkgVer ? '@' + pkgVer : ''}`;
274
- const specMsg = npmSpec === ext ? '' : ` using NPM install spec '${npmSpec}'`;
275
- const msg = `Installing '${ext}'${specMsg}`;
318
+ const specMsg =
319
+ npmSpec === installSpec ? '' : ` using NPM install spec '${npmSpec}'`;
320
+ const msg = `Installing '${installSpec}'${specMsg}`;
276
321
  try {
277
- const pkgJsonData = await spinWith(this.isJsonOutput, msg, async () => (
278
- await npm.installPackage(this.config.appiumHome, pkgName, {
279
- pkgVer
280
- })
281
- ));
282
- return this.getExtensionFields(pkgJsonData);
322
+ const pkgJsonData = await spinWith(
323
+ this.isJsonOutput,
324
+ msg,
325
+ async () =>
326
+ await npm.installPackage(this.config.appiumHome, pkgName, {
327
+ pkgVer,
328
+ })
329
+ );
330
+ return this.getExtensionFields(pkgJsonData, installSpec);
283
331
  } catch (err) {
284
- throw new Error(`Encountered an error when installing package: ${err.message}`);
332
+ throw new Error(
333
+ `Encountered an error when installing package: ${err.message}`
334
+ );
285
335
  }
286
336
  }
287
337
 
@@ -303,31 +353,38 @@ class ExtensionCommand {
303
353
  * load as the main driver class, or to be able to detect incompatibilities between driver and
304
354
  * appium versions.
305
355
  *
306
- * @param {ExtPackageJson<ExtType>} pkgJsonData - the package.json data for a driver module, as if it had been
307
- * straightforwardly 'require'd
356
+ * @param {ExtPackageJson<ExtType>} pkgJsonData - the package.json data for a driver module, as if it had been straightforwardly 'require'd
357
+ * @param {string} installSpec
308
358
  * @returns {ExtensionFields<ExtType>}
309
359
  */
310
- getExtensionFields (pkgJsonData) {
360
+ getExtensionFields (pkgJsonData, installSpec) {
311
361
  if (!pkgJsonData.appium) {
312
- throw new Error(`Installed driver did not have an 'appium' section in its ` +
313
- `package.json file as expected`);
362
+ throw new Error(
363
+ `Installed driver did not have an 'appium' section in its ` +
364
+ `package.json file as expected`
365
+ );
314
366
  }
315
367
  const {appium, name, version} = pkgJsonData;
316
- this.validateExtensionFields(appium);
368
+ this.validateExtensionFields(appium, installSpec);
317
369
  /** @type {unknown} */
318
370
  const result = {...appium, pkgName: name, version};
319
- return /** @type {ExtensionFields<ExtType>} */(result);
371
+ return /** @type {ExtensionFields<ExtType>} */ (result);
320
372
  }
321
373
 
322
374
  /**
323
375
  * For any package.json fields which a particular type of extension requires, validate the
324
376
  * presence and form of those fields on the package.json data, throwing an error if anything is
377
+
378
+ /**
379
+ * For any `package.json` fields which a particular type of extension requires, validate the
380
+ * presence and form of those fields on the `package.json` data, throwing an error if anything is
325
381
  * amiss.
326
382
  *
327
- * @param {ExtMetadata<ExtType>} appiumPkgData - the data in the "appium" field of package.json for an extension
383
+ * @param {ExtMetadata<ExtType>} extMetadata - the data in the "appium" field of `package.json` for an extension
384
+ * @param {string} installSpec - Extension name/spec
328
385
  */
329
386
  // eslint-disable-next-line no-unused-vars
330
- validateExtensionFields (appiumPkgData) {
387
+ validateExtensionFields (extMetadata, installSpec) {
331
388
  throw new Error('Must be implemented in final class');
332
389
  }
333
390
 
@@ -337,17 +394,22 @@ class ExtensionCommand {
337
394
  * @param {UninstallOpts} opts
338
395
  * @return {Promise<ExtRecord<ExtType>>} map of all installed extension names to extension data
339
396
  */
340
- async _uninstall ({ext}) {
341
- if (!this.config.isInstalled(ext)) {
342
- throw new Error(`Can't uninstall ${this.type} '${ext}'; it is not installed`);
397
+ async _uninstall ({installSpec}) {
398
+ if (!this.config.isInstalled(installSpec)) {
399
+ throw new Error(
400
+ `Can't uninstall ${this.type} '${installSpec}'; it is not installed`
401
+ );
343
402
  }
344
- const installPath = this.config.getInstallPath(ext);
403
+ const installPath = this.config.getInstallPath(installSpec);
345
404
  try {
346
405
  await fs.rimraf(installPath);
347
406
  } finally {
348
- await this.config.removeExtension(ext);
407
+ await this.config.removeExtension(installSpec);
349
408
  }
350
- log(this.isJsonOutput, `Successfully uninstalled ${this.type} '${ext}'`.green);
409
+ log(
410
+ this.isJsonOutput,
411
+ `Successfully uninstalled ${this.type} '${installSpec}'`.green
412
+ );
351
413
  return this.config.installedExtensions;
352
414
  }
353
415
 
@@ -357,13 +419,17 @@ class ExtensionCommand {
357
419
  * @param {ExtensionUpdateOpts} updateSpec
358
420
  * @return {Promise<ExtensionUpdateResult>}
359
421
  */
360
- async _update ({ext, unsafe}) {
361
- const shouldUpdateAll = ext === UPDATE_ALL;
422
+ async _update ({installSpec, unsafe}) {
423
+ const shouldUpdateAll = installSpec === UPDATE_ALL;
362
424
  // if we're specifically requesting an update for an extension, make sure it's installed
363
- if (!shouldUpdateAll && !this.config.isInstalled(ext)) {
364
- throw new Error(`The ${this.type} '${ext}' was not installed, so can't be updated`);
425
+ if (!shouldUpdateAll && !this.config.isInstalled(installSpec)) {
426
+ throw new Error(
427
+ `The ${this.type} '${installSpec}' was not installed, so can't be updated`
428
+ );
365
429
  }
366
- const extsToUpdate = shouldUpdateAll ? Object.keys(this.config.installedExtensions) : [ext];
430
+ const extsToUpdate = shouldUpdateAll
431
+ ? Object.keys(this.config.installedExtensions)
432
+ : [installSpec];
367
433
 
368
434
  // 'errors' will have ext names as keys and error objects as values
369
435
  /** @type {Record<string,Error>} */
@@ -376,24 +442,40 @@ class ExtensionCommand {
376
442
 
377
443
  for (const e of extsToUpdate) {
378
444
  try {
379
- await spinWith(this.isJsonOutput, `Checking if ${this.type} '${e}' is updatable`, () => {
380
- if (this.config.installedExtensions[e].installType !== INSTALL_TYPE_NPM) {
381
- throw new NotUpdatableError();
445
+ await spinWith(
446
+ this.isJsonOutput,
447
+ `Checking if ${this.type} '${e}' is updatable`,
448
+ () => {
449
+ if (
450
+ this.config.installedExtensions[e].installType !==
451
+ INSTALL_TYPE_NPM
452
+ ) {
453
+ throw new NotUpdatableError();
454
+ }
382
455
  }
383
- });
384
- const update = await spinWith(this.isJsonOutput, `Checking if ${this.type} '${e}' needs an update`, async () => {
385
- const update = await this.checkForExtensionUpdate(e);
386
- if (!(update.safeUpdate || update.unsafeUpdate)) {
387
- throw new NoUpdatesAvailableError();
456
+ );
457
+ const update = await spinWith(
458
+ this.isJsonOutput,
459
+ `Checking if ${this.type} '${e}' needs an update`,
460
+ async () => {
461
+ const update = await this.checkForExtensionUpdate(e);
462
+ if (!(update.safeUpdate || update.unsafeUpdate)) {
463
+ throw new NoUpdatesAvailableError();
464
+ }
465
+ return update;
388
466
  }
389
- return update;
390
- });
467
+ );
391
468
  if (!unsafe && !update.safeUpdate) {
392
- throw new Error(`The ${this.type} '${e}' has a major revision update ` +
393
- `(${update.current} => ${update.unsafeUpdate}), which could include ` +
394
- `breaking changes. If you want to apply this update, re-run with --unsafe`);
469
+ throw new Error(
470
+ `The ${this.type} '${e}' has a major revision update ` +
471
+ `(${update.current} => ${update.unsafeUpdate}), which could include ` +
472
+ `breaking changes. If you want to apply this update, re-run with --unsafe`
473
+ );
395
474
  }
396
- const updateVer = unsafe && update.unsafeUpdate ? update.unsafeUpdate : update.safeUpdate;
475
+ const updateVer =
476
+ unsafe && update.unsafeUpdate
477
+ ? update.unsafeUpdate
478
+ : update.safeUpdate;
397
479
  await spinWith(
398
480
  this.isJsonOutput,
399
481
  `Updating driver '${e}' from ${update.current} to ${updateVer}`,
@@ -407,12 +489,18 @@ class ExtensionCommand {
407
489
 
408
490
  log(this.isJsonOutput, 'Update report:');
409
491
  for (const [e, update] of _.toPairs(updates)) {
410
- log(this.isJsonOutput, `- ${this.type} ${e} updated: ${update.from} => ${update.to}`.green);
492
+ log(
493
+ this.isJsonOutput,
494
+ `- ${this.type} ${e} updated: ${update.from} => ${update.to}`.green
495
+ );
411
496
  }
412
497
  for (const [e, err] of _.toPairs(errors)) {
413
498
  if (err instanceof NotUpdatableError) {
414
- log(this.isJsonOutput, `- '${e}' was not installed via npm, so we could not check ` +
415
- `for updates`.yellow);
499
+ log(
500
+ this.isJsonOutput,
501
+ `- '${e}' was not installed via npm, so we could not check ` +
502
+ `for updates`.yellow
503
+ );
416
504
  } else if (err instanceof NoUpdatesAvailableError) {
417
505
  log(this.isJsonOutput, `- '${e}' had no updates available`.yellow);
418
506
  } else {
@@ -436,8 +524,15 @@ class ExtensionCommand {
436
524
  // this is a helper method, 'ext' is assumed to already be installed here, and of the npm
437
525
  // install type
438
526
  const {version, pkgName} = this.config.installedExtensions[ext];
439
- let unsafeUpdate = await npm.getLatestVersion(this.config.appiumHome, pkgName);
440
- let safeUpdate = await npm.getLatestSafeUpgradeVersion(this.config.appiumHome, pkgName, version);
527
+ let unsafeUpdate = await npm.getLatestVersion(
528
+ this.config.appiumHome,
529
+ pkgName
530
+ );
531
+ let safeUpdate = await npm.getLatestSafeUpgradeVersion(
532
+ this.config.appiumHome,
533
+ pkgName,
534
+ version
535
+ );
441
536
  if (!util.compareVersions(unsafeUpdate, '>', version)) {
442
537
  // the latest version is not greater than the current version, so there's no possible update
443
538
  unsafeUpdate = null;
@@ -458,16 +553,20 @@ class ExtensionCommand {
458
553
  * Actually update an extension installed by NPM, using the NPM cli. And update the installation
459
554
  * manifest.
460
555
  *
461
- * @param {string} ext - name of extension to update
556
+ * @param {string} installSpec - name of extension to update
462
557
  * @param {string} version - version string identifier to update extension to
463
558
  * @returns {Promise<void>}
464
559
  */
465
- async updateExtension (ext, version) {
466
- const {pkgName} = this.config.installedExtensions[ext];
467
- await fs.rimraf(this.config.getInstallPath(ext));
468
- const extData = await this.installViaNpm({ext, pkgName, pkgVer: version});
469
- delete extData[/** @type {string} */(`${this.type}Name`)];
470
- await this.config.updateExtension(ext, extData);
560
+ async updateExtension (installSpec, version) {
561
+ const {pkgName} = this.config.installedExtensions[installSpec];
562
+ await fs.rimraf(this.config.getInstallPath(installSpec));
563
+ const extData = await this.installViaNpm({
564
+ installSpec,
565
+ pkgName,
566
+ pkgVer: version,
567
+ });
568
+ delete extData[/** @type {string} */ (`${this.type}Name`)];
569
+ await this.config.updateExtension(installSpec, extData);
471
570
  }
472
571
 
473
572
  /**
@@ -481,33 +580,37 @@ class ExtensionCommand {
481
580
  * @param {RunOptions} opts
482
581
  * @return {Promise<RunOutput>}
483
582
  */
484
- async _run ({ext, scriptName}) {
485
- if (!_.has(this.config.installedExtensions, ext)) {
583
+ async _run ({installSpec, scriptName}) {
584
+ if (!_.has(this.config.installedExtensions, installSpec)) {
486
585
  throw new Error(`please install the ${this.type} first`);
487
586
  }
488
587
 
489
- const extConfig = this.config.installedExtensions[ext];
588
+ const extConfig = this.config.installedExtensions[installSpec];
490
589
 
491
590
  // note: TS cannot understand that _.has() is a type guard
492
591
  if (!extConfig.scripts) {
493
- throw new Error(`The ${this.type} named '${ext}' does not contain the ` +
494
- `"scripts" field underneath the "appium" field in its package.json`);
592
+ throw new Error(
593
+ `The ${this.type} named '${installSpec}' does not contain the ` +
594
+ `"scripts" field underneath the "appium" field in its package.json`
595
+ );
495
596
  }
496
597
 
497
598
  const extScripts = extConfig.scripts;
498
599
 
499
600
  if (!_.isPlainObject(extScripts)) {
500
- throw new Error(`The ${this.type} named '${ext}' "scripts" field must be a plain object`);
601
+ throw new Error(
602
+ `The ${this.type} named '${installSpec}' "scripts" field must be a plain object`
603
+ );
501
604
  }
502
605
 
503
606
  if (!_.has(extScripts, scriptName)) {
504
- throw new Error(`The ${this.type} named '${ext}' does not support the script: '${scriptName}'`);
607
+ throw new Error(
608
+ `The ${this.type} named '${installSpec}' does not support the script: '${scriptName}'`
609
+ );
505
610
  }
506
611
 
507
- const runner = new SubProcess(process.execPath, [
508
- extScripts[scriptName]
509
- ], {
510
- cwd: this.config.getInstallPath(ext)
612
+ const runner = new SubProcess(process.execPath, [extScripts[scriptName]], {
613
+ cwd: this.config.getInstallPath(installSpec),
511
614
  });
512
615
 
513
616
  const output = new RingBuffer(50);
@@ -524,7 +627,10 @@ class ExtensionCommand {
524
627
  log(this.isJsonOutput, `${scriptName} successfully ran`.green);
525
628
  return {output: output.getBuff()};
526
629
  } catch (err) {
527
- log(this.isJsonOutput, `Encountered an error when running '${scriptName}': ${err.message}`.red);
630
+ log(
631
+ this.isJsonOutput,
632
+ `Encountered an error when running '${scriptName}': ${err.message}`.red
633
+ );
528
634
  return {error: err.message, output: output.getBuff()};
529
635
  }
530
636
  }
@@ -602,7 +708,7 @@ export {ExtensionCommand};
602
708
  /**
603
709
  * Options for {@linkcode ExtensionCommand._run}.
604
710
  * @typedef RunOptions
605
- * @property {string} ext - name of the extension to run a script from
711
+ * @property {string} installSpec - name of the extension to run a script from
606
712
  * @property {string} scriptName - name of the script to run
607
713
  */
608
714
 
@@ -617,7 +723,7 @@ export {ExtensionCommand};
617
723
  /**
618
724
  * Options for {@linkcode ExtensionCommand._update}.
619
725
  * @typedef ExtensionUpdateOpts
620
- * @property {string} ext - the name of the extension to update
726
+ * @property {string} installSpec - the name of the extension to update
621
727
  * @property {boolean} unsafe - if true, will perform unsafe updates past major revision boundaries
622
728
  */
623
729
 
@@ -638,7 +744,7 @@ export {ExtensionCommand};
638
744
  /**
639
745
  * Options for {@linkcode ExtensionCommand._uninstall}.
640
746
  * @typedef UninstallOpts
641
- * @property {string} ext - the name or spec of an extension to uninstall
747
+ * @property {string} installSpec - the name or spec of an extension to uninstall
642
748
  */
643
749
 
644
750
  /**
@@ -651,7 +757,7 @@ export {ExtensionCommand};
651
757
  /**
652
758
  * Options for {@linkcode ExtensionCommand.installViaNpm}
653
759
  * @typedef InstallViaNpmArgs
654
- * @property {string} ext - the name or spec of an extension to install
760
+ * @property {string} installSpec - the name or spec of an extension to install
655
761
  * @property {string} pkgName - the NPM package name of the extension
656
762
  * @property {string} [pkgVer] - the specific version of the NPM package
657
763
  */
@@ -667,7 +773,7 @@ export {ExtensionCommand};
667
773
  /**
668
774
  * Options for {@linkcode ExtensionCommand._install}
669
775
  * @typedef InstallArgs
670
- * @property {string} ext - the name or spec of an extension to install
776
+ * @property {string} installSpec - the name or spec of an extension to install
671
777
  * @property {import('../../types/appium-manifest').InstallType} installType - how to install this extension. One of the INSTALL_TYPES
672
778
  * @property {string} [packageName] - for git/github installs, the extension node package name
673
779
  */
package/lib/cli/parser.js CHANGED
@@ -99,8 +99,9 @@ class ArgParser {
99
99
  * If no subcommand is passed in, this method will inject the `server` subcommand.
100
100
  *
101
101
  * `ArgParser.prototype.parse_args` is an alias of this method.
102
+ * @template [T=import('../../types').WithServerSubcommand]
102
103
  * @param {string[]} [args] - Array of arguments, ostensibly from `process.argv`. Gathers args from `process.argv` if not provided.
103
- * @returns {import('../../types/cli').ParsedArgs} - The parsed arguments
104
+ * @returns {import('../../types').Args<T>} - The parsed arguments
104
105
  */
105
106
  parseArgs (args = process.argv.slice(2)) {
106
107
  if (!NON_SERVER_ARGS.has(args[0])) {