appium 2.0.0-beta.57 → 2.0.0-beta.58

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 (76) hide show
  1. package/README.md +3 -2
  2. package/build/lib/appium.d.ts +43 -35
  3. package/build/lib/appium.d.ts.map +1 -1
  4. package/build/lib/appium.js +37 -29
  5. package/build/lib/appium.js.map +1 -1
  6. package/build/lib/cli/args.d.ts.map +1 -1
  7. package/build/lib/cli/args.js +10 -0
  8. package/build/lib/cli/args.js.map +1 -1
  9. package/build/lib/cli/driver-command.d.ts +7 -7
  10. package/build/lib/cli/driver-command.js +7 -7
  11. package/build/lib/cli/driver-command.js.map +1 -1
  12. package/build/lib/cli/extension-command.d.ts +37 -34
  13. package/build/lib/cli/extension-command.d.ts.map +1 -1
  14. package/build/lib/cli/extension-command.js +67 -44
  15. package/build/lib/cli/extension-command.js.map +1 -1
  16. package/build/lib/cli/extension.d.ts +5 -5
  17. package/build/lib/cli/extension.d.ts.map +1 -1
  18. package/build/lib/cli/extension.js +1 -1
  19. package/build/lib/cli/extension.js.map +1 -1
  20. package/build/lib/cli/plugin-command.d.ts +7 -7
  21. package/build/lib/cli/plugin-command.js +7 -7
  22. package/build/lib/cli/plugin-command.js.map +1 -1
  23. package/build/lib/constants.d.ts +8 -1
  24. package/build/lib/constants.d.ts.map +1 -1
  25. package/build/lib/constants.js +9 -2
  26. package/build/lib/constants.js.map +1 -1
  27. package/build/lib/extension/driver-config.d.ts +6 -6
  28. package/build/lib/extension/driver-config.d.ts.map +1 -1
  29. package/build/lib/extension/driver-config.js +5 -7
  30. package/build/lib/extension/driver-config.js.map +1 -1
  31. package/build/lib/extension/extension-config.d.ts +31 -10
  32. package/build/lib/extension/extension-config.d.ts.map +1 -1
  33. package/build/lib/extension/extension-config.js +44 -24
  34. package/build/lib/extension/extension-config.js.map +1 -1
  35. package/build/lib/extension/manifest-migrations.d.ts.map +1 -1
  36. package/build/lib/extension/manifest-migrations.js +29 -13
  37. package/build/lib/extension/manifest-migrations.js.map +1 -1
  38. package/build/lib/extension/manifest.d.ts +5 -5
  39. package/build/lib/extension/manifest.d.ts.map +1 -1
  40. package/build/lib/extension/manifest.js +19 -12
  41. package/build/lib/extension/manifest.js.map +1 -1
  42. package/build/lib/main.d.ts.map +1 -1
  43. package/build/lib/main.js +3 -3
  44. package/build/lib/main.js.map +1 -1
  45. package/build/lib/schema/cli-args.d.ts +1 -1
  46. package/build/lib/schema/cli-args.d.ts.map +1 -1
  47. package/build/lib/schema/cli-args.js +1 -1
  48. package/build/lib/utils.d.ts +118 -12
  49. package/build/lib/utils.d.ts.map +1 -1
  50. package/build/lib/utils.js +8 -10
  51. package/build/lib/utils.js.map +1 -1
  52. package/build/types/manifest/index.d.ts +4 -2
  53. package/build/types/manifest/index.d.ts.map +1 -1
  54. package/build/types/manifest/index.js +4 -2
  55. package/build/types/manifest/index.js.map +1 -1
  56. package/build/types/manifest/v4.d.ts +139 -0
  57. package/build/types/manifest/v4.d.ts.map +1 -0
  58. package/build/types/manifest/v4.js +3 -0
  59. package/build/types/manifest/v4.js.map +1 -0
  60. package/lib/appium.js +42 -31
  61. package/lib/cli/args.js +10 -0
  62. package/lib/cli/driver-command.js +7 -7
  63. package/lib/cli/extension-command.js +76 -54
  64. package/lib/cli/extension.js +5 -5
  65. package/lib/cli/plugin-command.js +7 -7
  66. package/lib/constants.js +9 -1
  67. package/lib/extension/driver-config.js +5 -8
  68. package/lib/extension/extension-config.js +42 -15
  69. package/lib/extension/manifest-migrations.js +31 -15
  70. package/lib/extension/manifest.js +26 -19
  71. package/lib/main.js +7 -4
  72. package/lib/schema/cli-args.js +1 -1
  73. package/lib/utils.js +8 -10
  74. package/package.json +9 -9
  75. package/types/manifest/index.ts +4 -3
  76. package/types/manifest/v4.ts +161 -0
@@ -9,10 +9,12 @@ import {
9
9
  INSTALL_TYPE_GIT,
10
10
  INSTALL_TYPE_GITHUB,
11
11
  INSTALL_TYPE_LOCAL,
12
+ INSTALL_TYPE_DEV,
12
13
  } from '../extension/extension-config';
13
14
  import {SubProcess} from 'teen_process';
14
15
  import {packageDidChange} from '../extension/package-changed';
15
16
  import {spawn} from 'child_process';
17
+ import {inspect} from 'node:util';
16
18
 
17
19
  const UPDATE_ALL = 'installed';
18
20
 
@@ -32,7 +34,7 @@ function receiptToManifest(receipt) {
32
34
  /**
33
35
  * @template {ExtensionType} ExtType
34
36
  */
35
- class ExtensionCommand {
37
+ class ExtensionCliCommand {
36
38
  /**
37
39
  * This is the `DriverConfig` or `PluginConfig`, depending on `ExtType`.
38
40
  * @type {ExtensionConfig<ExtType>}
@@ -99,41 +101,40 @@ class ExtensionCommand {
99
101
 
100
102
  /**
101
103
  * List extensions
102
- *
104
+ * @template {ExtensionType} ExtType
103
105
  * @param {ListOptions} opts
104
- * @return {Promise<ExtensionListData>} map of extension names to extension data
106
+ * @return {Promise<ExtensionList<ExtType>>} map of extension names to extension data
105
107
  */
106
- async list({showInstalled, showUpdates}) {
107
- const lsMsg = `Listing ${showInstalled ? 'installed' : 'available'} ${this.type}s`;
108
+ async list({showInstalled, showUpdates, verbose = false}) {
109
+ let lsMsg = `Listing ${showInstalled ? 'installed' : 'available'} ${this.type}s`;
110
+ if (verbose) {
111
+ lsMsg += ' (verbose mode)';
112
+ }
108
113
  const installedNames = Object.keys(this.config.installedExtensions);
109
114
  const knownNames = Object.keys(this.knownExtensions);
110
- const exts = [...installedNames, ...knownNames].reduce(
111
- (acc, name) => {
112
- if (!acc[name]) {
113
- if (installedNames.includes(name)) {
114
- acc[name] = {
115
- ...this.config.installedExtensions[name],
116
- installed: true,
117
- };
118
- } else if (!showInstalled) {
119
- acc[name] = {pkgName: this.knownExtensions[name], installed: false};
120
- }
115
+ const listData = [...installedNames, ...knownNames].reduce((acc, name) => {
116
+ if (!acc[name]) {
117
+ if (installedNames.includes(name)) {
118
+ acc[name] = {
119
+ .../** @type {Partial<ExtManifest<ExtType>>} */ (this.config.installedExtensions[name]),
120
+ installed: true,
121
+ };
122
+ } else if (!showInstalled) {
123
+ acc[name] = /** @type {ExtensionListData<ExtType>} */ ({
124
+ pkgName: this.knownExtensions[name],
125
+ installed: false,
126
+ });
121
127
  }
122
- return acc;
123
- },
124
- /**
125
- * This accumulator contains either {@linkcode UninstalledExtensionLIstData} _or_
126
- * {@linkcode InstalledExtensionListData} without upgrade information (which is added by the below code block)
127
- * @type {Record<string,Partial<InstalledExtensionListData>|UninstalledExtensionListData>}
128
- */ ({})
129
- );
128
+ }
129
+ return acc;
130
+ }, /** @type {ExtensionList<ExtType>} */ ({}));
130
131
 
131
132
  // if we want to show whether updates are available, put that behind a spinner
132
133
  await spinWith(this.isJsonOutput, lsMsg, async () => {
133
134
  if (!showUpdates) {
134
135
  return;
135
136
  }
136
- for (const [ext, data] of _.toPairs(exts)) {
137
+ for (const [ext, data] of _.toPairs(listData)) {
137
138
  if (!data.installed || data.installType !== INSTALL_TYPE_NPM) {
138
139
  // don't need to check for updates on exts that aren't installed
139
140
  // also don't need to check for updates on non-npm exts
@@ -150,7 +151,12 @@ class ExtensionCommand {
150
151
  }
151
152
  });
152
153
 
153
- const listData = /** @type {ExtensionListData} */ (exts);
154
+ /**
155
+ * Type guard to narrow "installed" extensions, which have more data
156
+ * @param {any} data
157
+ * @returns {data is InstalledExtensionListData<ExtType>}
158
+ */
159
+ const extIsInstalled = (data) => Boolean(data.installed);
154
160
 
155
161
  // if we're just getting the data, short circuit return here since we don't need to do any
156
162
  // formatting logic
@@ -158,12 +164,16 @@ class ExtensionCommand {
158
164
  return listData;
159
165
  }
160
166
 
167
+ if (verbose) {
168
+ this.log.log(inspect(listData, {colors: true, depth: null}));
169
+ return listData;
170
+ }
161
171
  for (const [name, data] of _.toPairs(listData)) {
162
172
  let installTxt = ' [not installed]'.grey;
163
173
  let updateTxt = '';
164
174
  let upToDateTxt = '';
165
175
  let unsafeUpdateTxt = '';
166
- if (data.installed) {
176
+ if (extIsInstalled(data)) {
167
177
  const {
168
178
  installType,
169
179
  installSpec,
@@ -182,8 +192,11 @@ class ExtensionCommand {
182
192
  case INSTALL_TYPE_LOCAL:
183
193
  typeTxt = `(linked from ${installSpec})`.magenta;
184
194
  break;
195
+ case INSTALL_TYPE_DEV:
196
+ typeTxt = '(dev mode)';
197
+ break;
185
198
  default:
186
- typeTxt = '(NPM)';
199
+ typeTxt = '(npm)';
187
200
  }
188
201
  installTxt = `@${version.yellow} ${('[installed ' + typeTxt + ']').green}`;
189
202
 
@@ -513,7 +526,12 @@ class ExtensionCommand {
513
526
  `Can't uninstall ${this.type} '${installSpec}'; it is not installed`
514
527
  );
515
528
  }
516
- const pkgName = this.config.installedExtensions[installSpec].pkgName;
529
+ const extRecord = this.config.installedExtensions[installSpec];
530
+ if (extRecord.installType === INSTALL_TYPE_DEV) {
531
+ this.log.warn(`Cannot uninstall ${this.type} "${installSpec}" because it is in development!`);
532
+ return this.config.installedExtensions;
533
+ }
534
+ const pkgName = extRecord.pkgName;
517
535
  await npm.uninstallPackage(this.config.appiumHome, pkgName);
518
536
  await this.config.removeExtension(installSpec);
519
537
  this.log.ok(`Successfully uninstalled ${this.type} '${installSpec}'`.green);
@@ -771,11 +789,11 @@ class ExtensionCommand {
771
789
  }
772
790
  }
773
791
 
774
- export default ExtensionCommand;
775
- export {ExtensionCommand};
792
+ export default ExtensionCliCommand;
793
+ export {ExtensionCliCommand as ExtensionCommand};
776
794
 
777
795
  /**
778
- * Options for the {@linkcode ExtensionCommand} constructor
796
+ * Options for the {@linkcode ExtensionCliCommand} constructor
779
797
  * @template {ExtensionType} ExtType
780
798
  * @typedef ExtensionCommandOptions
781
799
  * @property {ExtensionConfig<ExtType>} config - the `DriverConfig` or `PluginConfig` instance used for this command
@@ -783,14 +801,15 @@ export {ExtensionCommand};
783
801
  */
784
802
 
785
803
  /**
786
- * Extra stuff about extensions; used indirectly by {@linkcode ExtensionCommand.list}.
804
+ * Extra stuff about extensions; used indirectly by {@linkcode ExtensionCliCommand.list}.
787
805
  *
788
- * @typedef ExtensionMetadata
806
+ * @typedef ExtensionListMetadata
789
807
  * @property {boolean} installed - If `true`, the extension is installed
790
- * @property {string?} updateVersion - If the extension is installed, the version it can be updated to
791
- * @property {string?} unsafeUpdateVersion - Same as above, but a major version bump
792
808
  * @property {boolean} upToDate - If the extension is installed and the latest
793
- * @property {string?} updateError - Update check error message (if present)
809
+ * @property {string|null} updateVersion - If the extension is installed, the version it can be updated to
810
+ * @property {string|null} unsafeUpdateVersion - Same as above, but a major version bump
811
+ * @property {string} [updateError] - Update check error message (if present)
812
+ * @property {boolean} [devMode] - If Appium is run from an extension's working copy
794
813
  */
795
814
 
796
815
  /**
@@ -830,22 +849,24 @@ export {ExtensionCommand};
830
849
  */
831
850
 
832
851
  /**
833
- * Possible return value for {@linkcode ExtensionCommand.list}
834
- * @typedef {Partial<InstalledExtensionListData> & {pkgName: string, installed: false}} UninstalledExtensionListData
852
+ * Possible return value for {@linkcode ExtensionCliCommand.list}
853
+ * @template {ExtensionType} ExtType
854
+ * @typedef {Partial<ExtManifest<ExtType>> & Partial<ExtensionListMetadata>} ExtensionListData
835
855
  */
836
856
 
837
857
  /**
838
- * Possible return value for {@linkcode ExtensionCommand.list}
839
- * @typedef {import('appium/types').InternalMetadata & ExtensionMetadata} InstalledExtensionListData
858
+ * @template {ExtensionType} ExtType
859
+ * @typedef {ExtManifest<ExtType> & ExtensionListMetadata} InstalledExtensionListData
840
860
  */
841
861
 
842
862
  /**
843
- * Return value of {@linkcode ExtensionCommand.list}.
844
- * @typedef {Record<string,InstalledExtensionListData|UninstalledExtensionListData>} ExtensionListData
863
+ * Return value of {@linkcode ExtensionCliCommand.list}.
864
+ * @template {ExtensionType} ExtType
865
+ * @typedef {Record<string,ExtensionListData<ExtType>>} ExtensionList
845
866
  */
846
867
 
847
868
  /**
848
- * Options for {@linkcode ExtensionCommand._run}.
869
+ * Options for {@linkcode ExtensionCliCommand._run}.
849
870
  * @typedef RunOptions
850
871
  * @property {string} installSpec - name of the extension to run a script from
851
872
  * @property {string} scriptName - name of the script to run
@@ -854,7 +875,7 @@ export {ExtensionCommand};
854
875
  */
855
876
 
856
877
  /**
857
- * Return value of {@linkcode ExtensionCommand._run}
878
+ * Return value of {@linkcode ExtensionCliCommand._run}
858
879
  *
859
880
  * @typedef RunOutput
860
881
  * @property {string} [error] - error message if script ran unsuccessfully, otherwise undefined
@@ -862,41 +883,41 @@ export {ExtensionCommand};
862
883
  */
863
884
 
864
885
  /**
865
- * Options for {@linkcode ExtensionCommand._update}.
886
+ * Options for {@linkcode ExtensionCliCommand._update}.
866
887
  * @typedef ExtensionUpdateOpts
867
888
  * @property {string} installSpec - the name of the extension to update
868
889
  * @property {boolean} unsafe - if true, will perform unsafe updates past major revision boundaries
869
890
  */
870
891
 
871
892
  /**
872
- * Return value of {@linkcode ExtensionCommand._update}.
893
+ * Return value of {@linkcode ExtensionCliCommand._update}.
873
894
  * @typedef ExtensionUpdateResult
874
895
  * @property {Record<string,Error>} errors - map of ext names to error objects
875
896
  * @property {Record<string,UpdateReport>} updates - map of ext names to {@linkcode UpdateReport}s
876
897
  */
877
898
 
878
899
  /**
879
- * Part of result of {@linkcode ExtensionCommand._update}.
900
+ * Part of result of {@linkcode ExtensionCliCommand._update}.
880
901
  * @typedef UpdateReport
881
902
  * @property {string} from - version the extension was updated from
882
903
  * @property {string} to - version the extension was updated to
883
904
  */
884
905
 
885
906
  /**
886
- * Options for {@linkcode ExtensionCommand._uninstall}.
907
+ * Options for {@linkcode ExtensionCliCommand._uninstall}.
887
908
  * @typedef UninstallOpts
888
909
  * @property {string} installSpec - the name or spec of an extension to uninstall
889
910
  */
890
911
 
891
912
  /**
892
- * Used by {@linkcode ExtensionCommand.getPostInstallText}
913
+ * Used by {@linkcode ExtensionCliCommand.getPostInstallText}
893
914
  * @typedef ExtensionArgs
894
915
  * @property {string} extName - the name of an extension
895
916
  * @property {object} extData - the data for an installed extension
896
917
  */
897
918
 
898
919
  /**
899
- * Options for {@linkcode ExtensionCommand.installViaNpm}
920
+ * Options for {@linkcode ExtensionCliCommand.installViaNpm}
900
921
  * @typedef InstallViaNpmArgs
901
922
  * @property {string} installSpec - the name or spec of an extension to install
902
923
  * @property {string} pkgName - the NPM package name of the extension
@@ -905,7 +926,7 @@ export {ExtensionCommand};
905
926
  */
906
927
 
907
928
  /**
908
- * Object returned by {@linkcode ExtensionCommand.checkForExtensionUpdate}
929
+ * Object returned by {@linkcode ExtensionCliCommand.checkForExtensionUpdate}
909
930
  * @typedef PossibleUpdates
910
931
  * @property {string} current - current version
911
932
  * @property {string?} safeUpdate - version we can safely update to if it exists, or null
@@ -913,7 +934,7 @@ export {ExtensionCommand};
913
934
  */
914
935
 
915
936
  /**
916
- * Options for {@linkcode ExtensionCommand._install}
937
+ * Options for {@linkcode ExtensionCliCommand._install}
917
938
  * @typedef InstallOpts
918
939
  * @property {string} installSpec - the name or spec of an extension to install
919
940
  * @property {InstallType} installType - how to install this extension. One of the INSTALL_TYPES
@@ -929,10 +950,11 @@ export {ExtensionCommand};
929
950
  * @typedef ListOptions
930
951
  * @property {boolean} showInstalled - whether should show only installed extensions
931
952
  * @property {boolean} showUpdates - whether should show available updates
953
+ * @property {boolean} [verbose] - whether to show additional data from the extension
932
954
  */
933
955
 
934
956
  /**
935
- * Opts for {@linkcode ExtensionCommand.getInstallationReceipt}
957
+ * Opts for {@linkcode ExtensionCliCommand.getInstallationReceipt}
936
958
  * @template {ExtensionType} ExtType
937
959
  * @typedef GetInstallationReceiptOpts
938
960
  * @property {string} installPath
@@ -1,14 +1,14 @@
1
1
  /* eslint-disable no-console */
2
2
  import {DRIVER_TYPE, PLUGIN_TYPE} from '../constants';
3
3
  import {isExtensionCommandArgs} from '../utils';
4
- import DriverCommand from './driver-command';
5
- import PluginCommand from './plugin-command';
4
+ import DriverCliCommand from './driver-command';
5
+ import PluginCliCommand from './plugin-command';
6
6
  import {errAndQuit, JSON_SPACES} from './utils';
7
7
 
8
8
  export const commandClasses = Object.freeze(
9
9
  /** @type {const} */ ({
10
- [DRIVER_TYPE]: DriverCommand,
11
- [PLUGIN_TYPE]: PluginCommand,
10
+ [DRIVER_TYPE]: DriverCliCommand,
11
+ [PLUGIN_TYPE]: PluginCliCommand,
12
12
  })
13
13
  );
14
14
 
@@ -59,7 +59,7 @@ export {runExtensionCommand};
59
59
 
60
60
  /**
61
61
  * @template {ExtensionType} ExtType
62
- * @typedef {ExtType extends DriverType ? Class<DriverCommand> : ExtType extends PluginType ? Class<PluginCommand> : never} ExtCommand
62
+ * @typedef {ExtType extends DriverType ? Class<DriverCliCommand> : ExtType extends PluginType ? Class<PluginCliCommand> : never} ExtCommand
63
63
  */
64
64
 
65
65
  /**
@@ -1,13 +1,13 @@
1
1
  import _ from 'lodash';
2
- import ExtensionCommand from './extension-command';
2
+ import ExtensionCliCommand from './extension-command';
3
3
  import {KNOWN_PLUGINS} from '../constants';
4
4
 
5
5
  const REQ_PLUGIN_FIELDS = ['pluginName', 'mainClass'];
6
6
 
7
7
  /**
8
- * @extends {ExtensionCommand<PluginType>}
8
+ * @extends {ExtensionCliCommand<PluginType>}
9
9
  */
10
- export default class PluginCommand extends ExtensionCommand {
10
+ export default class PluginCliCommand extends ExtensionCliCommand {
11
11
  /**
12
12
  *
13
13
  * @param {import('./extension-command').ExtensionCommandOptions<PluginType>} opts
@@ -110,7 +110,7 @@ export default class PluginCommand extends ExtensionCommand {
110
110
  */
111
111
 
112
112
  /**
113
- * Options for {@linkcode PluginCommand.install}
113
+ * Options for {@linkcode PluginCliCommand.install}
114
114
  * @typedef PluginInstallOpts
115
115
  * @property {string} plugin - the name or spec of a plugin to install
116
116
  * @property {InstallType} installType - how to install this plugin. One of the INSTALL_TYPES
@@ -122,20 +122,20 @@ export default class PluginCommand extends ExtensionCommand {
122
122
  */
123
123
 
124
124
  /**
125
- * Options for {@linkcode PluginCommand.uninstall}
125
+ * Options for {@linkcode PluginCliCommand.uninstall}
126
126
  * @typedef PluginUninstallOpts
127
127
  * @property {string} plugin - the name or spec of a plugin to uninstall
128
128
  */
129
129
 
130
130
  /**
131
- * Options for {@linkcode PluginCommand.update}
131
+ * Options for {@linkcode PluginCliCommand.update}
132
132
  * @typedef PluginUpdateOpts
133
133
  * @property {string} plugin - the name of the plugin to update
134
134
  * @property {boolean} unsafe - if true, will perform unsafe updates past major revision boundaries
135
135
  */
136
136
 
137
137
  /**
138
- * Options for {@linkcode PluginCommand.run}.
138
+ * Options for {@linkcode PluginCliCommand.run}.
139
139
  * @typedef PluginRunOptions
140
140
  * @property {string} plugin - name of the plugin to run a script from
141
141
  * @property {string} scriptName - name of the script to run
package/lib/constants.js CHANGED
@@ -68,4 +68,12 @@ export const EXT_SUBCOMMAND_RUN = 'run';
68
68
  /**
69
69
  * Current revision of the manifest (`extensions.yaml`) schema
70
70
  */
71
- export const CURRENT_SCHEMA_REV = 3;
71
+ export const CURRENT_SCHEMA_REV = 4;
72
+
73
+ /**
74
+ * The default number of stack frames to show in a "long" stack trace, when enabled via `--long-stacktrace`
75
+ * @remarks This value may be increased in the future.
76
+ * @privateRemarks A value like `Infinity` may provide to have deleterious effects on
77
+ * memory usage, perf, and/or log output, and higher limits may be difficult to scan.
78
+ */
79
+ export const LONG_STACKTRACE_LIMIT = 100;
@@ -212,28 +212,29 @@ export class DriverConfig extends ExtensionConfig {
212
212
  }
213
213
 
214
214
  /**
215
- * @template T
215
+ * @template {ExtensionType} T
216
216
  * @typedef {import('appium/types').ExtMetadata<T>} ExtMetadata
217
217
  */
218
218
 
219
219
  /**
220
- * @template T
220
+ * @template {ExtensionType} T
221
221
  * @typedef {import('appium/types').ExtManifest<T>} ExtManifest
222
222
  */
223
223
 
224
224
  /**
225
+ * @typedef {import('@appium/types').ExtensionType} ExtensionType
225
226
  * @typedef {import('appium/types').ManifestData} ManifestData
226
227
  * @typedef {import('@appium/types').DriverType} DriverType
227
228
  * @typedef {import('./manifest').Manifest} Manifest
228
229
  */
229
230
 
230
231
  /**
231
- * @template T
232
+ * @template {ExtensionType} T
232
233
  * @typedef {import('appium/types').ExtRecord<T>} ExtRecord
233
234
  */
234
235
 
235
236
  /**
236
- * @template T
237
+ * @template {ExtensionType} T
237
238
  * @typedef {import('appium/types').ExtName<T>} ExtName
238
239
  */
239
240
 
@@ -244,7 +245,3 @@ export class DriverConfig extends ExtensionConfig {
244
245
  * @property {string} version
245
246
  * @property {string} driverName
246
247
  */
247
-
248
- /**
249
- * @typedef {import('@appium/types').Capabilities} Capabilities
250
- */
@@ -1,9 +1,9 @@
1
- import _ from 'lodash';
1
+ import {util} from '@appium/support';
2
2
  import B from 'bluebird';
3
+ import _ from 'lodash';
3
4
  import path from 'path';
4
5
  import resolveFrom from 'resolve-from';
5
6
  import {satisfies} from 'semver';
6
- import {util} from '@appium/support';
7
7
  import {commandClasses} from '../cli/extension';
8
8
  import {APPIUM_VER} from '../config';
9
9
  import log from '../logger';
@@ -13,17 +13,41 @@ import {
13
13
  registerSchema,
14
14
  } from '../schema/schema';
15
15
 
16
- const INSTALL_TYPE_NPM = 'npm';
17
- const INSTALL_TYPE_LOCAL = 'local';
18
- const INSTALL_TYPE_GITHUB = 'github';
19
- const INSTALL_TYPE_GIT = 'git';
16
+ /**
17
+ * "npm" install type
18
+ * Used when extension was installed by npm package name
19
+ * @remarks _All_ extensions are installed _by_ `npm`, but only this one means the package name was
20
+ * used to specify it
21
+ */
22
+ export const INSTALL_TYPE_NPM = 'npm';
23
+ /**
24
+ * "local" install type
25
+ * Used when extension was installed from a local path
26
+ */
27
+ export const INSTALL_TYPE_LOCAL = 'local';
28
+ /**
29
+ * "github" install type
30
+ * Used when extension was installed via GitHub URL
31
+ */
32
+ export const INSTALL_TYPE_GITHUB = 'github';
33
+ /**
34
+ * "git" install type
35
+ * Used when extensions was installed via Git URL
36
+ */
37
+ export const INSTALL_TYPE_GIT = 'git';
38
+ /**
39
+ * "dev" install type
40
+ * Used when automatically detected as a working copy
41
+ */
42
+ export const INSTALL_TYPE_DEV = 'dev';
20
43
 
21
44
  /** @type {Set<InstallType>} */
22
- const INSTALL_TYPES = new Set([
45
+ export const INSTALL_TYPES = new Set([
23
46
  INSTALL_TYPE_GIT,
24
47
  INSTALL_TYPE_GITHUB,
25
48
  INSTALL_TYPE_LOCAL,
26
49
  INSTALL_TYPE_NPM,
50
+ INSTALL_TYPE_DEV,
27
51
  ]);
28
52
 
29
53
  /**
@@ -54,7 +78,7 @@ export class ExtensionConfig {
54
78
  manifest;
55
79
 
56
80
  /**
57
- * @type {ExtensionListData|undefined}
81
+ * @type {import('../cli/extension-command').ExtensionList<ExtType>|undefined}
58
82
  */
59
83
  #listDataCache;
60
84
 
@@ -239,7 +263,7 @@ export class ExtensionConfig {
239
263
  * This is an expensive operation, so the result is cached. Currently, there is no
240
264
  * use case for invalidating the cache.
241
265
  * @protected
242
- * @returns {Promise<ExtensionListData>}
266
+ * @returns {Promise<import('../cli/extension-command').ExtensionList<ExtType>>}
243
267
  */
244
268
  async getListData() {
245
269
  if (this.#listDataCache) {
@@ -300,7 +324,10 @@ export class ExtensionConfig {
300
324
 
301
325
  if (_.isString(appiumVersion) && !satisfies(APPIUM_VER, appiumVersion)) {
302
326
  const listData = await this.getListData();
303
- const extListData = /** @type {InstalledExtensionListData} */ (listData[extName]);
327
+ const extListData =
328
+ /** @type {import('../cli/extension-command').ExtensionListData<ExtType>} */ (
329
+ listData[extName]
330
+ );
304
331
  if (extListData?.installed) {
305
332
  const {updateVersion, upToDate} = extListData;
306
333
  if (!upToDate) {
@@ -319,7 +346,10 @@ export class ExtensionConfig {
319
346
  }
320
347
  } else if (!_.isString(appiumVersion)) {
321
348
  const listData = await this.getListData();
322
- const extListData = /** @type {InstalledExtensionListData} */ (listData[extName]);
349
+ const extListData =
350
+ /** @type {import('../cli/extension-command').InstalledExtensionListData<ExtType>} */ (
351
+ listData[extName]
352
+ );
323
353
  if (!extListData?.upToDate && extListData?.updateVersion) {
324
354
  warnings.push(
325
355
  createPeerWarning(
@@ -544,6 +574,7 @@ export class ExtensionConfig {
544
574
  delete require.cache[reqResolved];
545
575
  }
546
576
  log.debug(`Requiring ${this.extensionType} at ${reqPath}`);
577
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
547
578
  const MainClass = require(reqPath)[mainClass];
548
579
  if (!MainClass) {
549
580
  throw new ReferenceError(
@@ -619,8 +650,6 @@ export class ExtensionConfig {
619
650
  }
620
651
  }
621
652
 
622
- export {INSTALL_TYPE_NPM, INSTALL_TYPE_GIT, INSTALL_TYPE_LOCAL, INSTALL_TYPE_GITHUB, INSTALL_TYPES};
623
-
624
653
  /**
625
654
  * An issue with the {@linkcode ExtManifest} for a particular extension.
626
655
  *
@@ -640,8 +669,6 @@ export {INSTALL_TYPE_NPM, INSTALL_TYPE_GIT, INSTALL_TYPE_LOCAL, INSTALL_TYPE_GIT
640
669
  /**
641
670
  * @typedef {import('@appium/types').ExtensionType} ExtensionType
642
671
  * @typedef {import('./manifest').Manifest} Manifest
643
- * @typedef {import('../cli/extension-command').ExtensionListData} ExtensionListData
644
- * @typedef {import('../cli/extension-command').InstalledExtensionListData} InstalledExtensionListData
645
672
  * @typedef {import('appium/types').InstallType} InstallType
646
673
  */
647
674
 
@@ -1,4 +1,4 @@
1
- import {DRIVER_TYPE, PLUGIN_TYPE} from '../constants';
1
+ import {CURRENT_SCHEMA_REV, DRIVER_TYPE, PLUGIN_TYPE} from '../constants';
2
2
  import log from '../logger';
3
3
 
4
4
  /**
@@ -12,6 +12,11 @@ import log from '../logger';
12
12
  */
13
13
  const SCHEMA_REV_3 = 3;
14
14
 
15
+ /**
16
+ * Constant for v4 of the schema rev.
17
+ */
18
+ const SCHEMA_REV_4 = 4;
19
+
15
20
  /**
16
21
  * Collection of functions to migrate from one version to another.
17
22
  *
@@ -20,7 +25,7 @@ const SCHEMA_REV_3 = 3;
20
25
  * itself will happen within {@linkcode Manifest.syncWithInstalledExtensions}; the extensions
21
26
  * will be checked and the manifest file updated per the state of the filesystem.
22
27
  *
23
- * @type {{[P in keyof ManifestDataVersions]?: Migration}}
28
+ * @type { {[P in keyof ManifestDataVersions]?: Migration} }
24
29
  */
25
30
  const Migrations = {
26
31
  /**
@@ -32,19 +37,32 @@ const Migrations = {
32
37
  * @type {Migration}
33
38
  */
34
39
  [SCHEMA_REV_3]: (manifest) => {
35
- let shouldSync = false;
36
40
  /** @type {Array<ExtManifest<PluginType>|ExtManifest<DriverType>>} */
37
41
  const allExtData = [
38
42
  ...Object.values(manifest.getExtensionData(DRIVER_TYPE)),
39
43
  ...Object.values(manifest.getExtensionData(PLUGIN_TYPE)),
40
44
  ];
41
- for (const metadata of allExtData) {
42
- if (!('installPath' in metadata)) {
43
- shouldSync = true;
44
- break;
45
- }
45
+ return allExtData.some((metadata) => !('installPath' in metadata));
46
+ },
47
+ /**
48
+ * Updates installed extensions to use `InstallType` of `dev` if appropriate.
49
+ *
50
+ * Previously, these types of extensions (automatically discovered) would use the default `InstallType` of `npm`, so we need
51
+ * to refresh any with this install type.
52
+ *
53
+ * This should only happen once; we do not want to re-check everything with `npm` install type
54
+ * every time.
55
+ * @type {Migration}
56
+ */
57
+ [SCHEMA_REV_4]: (manifest) => {
58
+ if (manifest.schemaRev < SCHEMA_REV_4) {
59
+ const allExtData = [
60
+ ...Object.values(manifest.getExtensionData(DRIVER_TYPE)),
61
+ ...Object.values(manifest.getExtensionData(PLUGIN_TYPE)),
62
+ ];
63
+ return allExtData.some((metadata) => metadata.installType === 'npm');
46
64
  }
47
- return shouldSync;
65
+ return false;
48
66
  },
49
67
  };
50
68
 
@@ -61,7 +79,7 @@ const Migrations = {
61
79
  * @returns {boolean} Whether the data was modified
62
80
  */
63
81
  function setSchemaRev(manifest, version) {
64
- if (manifest.schemaRev ?? 0 < version) {
82
+ if ((manifest.schemaRev ?? 0) < version) {
65
83
  manifest.setSchemaRev(version);
66
84
  return true;
67
85
  }
@@ -78,15 +96,13 @@ function setSchemaRev(manifest, version) {
78
96
  */
79
97
  export async function migrate(manifest) {
80
98
  let didChange = false;
81
- for await (const [v, migration] of Object.entries(Migrations)) {
82
- const version = /** @type {keyof ManifestDataVersions} */ (Number(v));
99
+ for await (const migration of Object.values(Migrations)) {
83
100
  didChange = (await migration(manifest)) || didChange;
84
- didChange = setSchemaRev(manifest, version) || didChange;
85
101
  }
86
-
102
+ didChange = setSchemaRev(manifest, CURRENT_SCHEMA_REV) || didChange;
87
103
  if (didChange) {
88
104
  // this is not _technically_ true, since we don't actually write the file here.
89
- log.info(`Upgraded extension manifest to schema v${manifest.schemaRev}`);
105
+ log.debug(`Upgraded extension manifest to schema v${manifest.schemaRev}`);
90
106
  }
91
107
 
92
108
  return didChange;