appium 2.0.0-beta.26 → 2.0.0-beta.29
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.
- package/build/lib/appium.d.ts +215 -0
- package/build/lib/appium.d.ts.map +1 -0
- package/build/lib/appium.js +62 -54
- package/build/lib/cli/args.d.ts +20 -0
- package/build/lib/cli/args.d.ts.map +1 -0
- package/build/lib/cli/args.js +1 -1
- package/build/lib/cli/driver-command.d.ts +36 -0
- package/build/lib/cli/driver-command.d.ts.map +1 -0
- package/build/lib/cli/driver-command.js +8 -7
- package/build/lib/cli/extension-command.d.ts +345 -0
- package/build/lib/cli/extension-command.d.ts.map +1 -0
- package/build/lib/cli/extension-command.js +52 -38
- package/build/lib/cli/extension.d.ts +14 -0
- package/build/lib/cli/extension.d.ts.map +1 -0
- package/build/lib/cli/extension.js +7 -2
- package/build/lib/cli/parser.d.ts +79 -0
- package/build/lib/cli/parser.d.ts.map +1 -0
- package/build/lib/cli/parser.js +1 -1
- package/build/lib/cli/plugin-command.d.ts +39 -0
- package/build/lib/cli/plugin-command.d.ts.map +1 -0
- package/build/lib/cli/plugin-command.js +6 -7
- package/build/lib/cli/utils.d.ts +29 -0
- package/build/lib/cli/utils.d.ts.map +1 -0
- package/build/lib/cli/utils.js +1 -1
- package/build/lib/config-file.d.ts +100 -0
- package/build/lib/config-file.d.ts.map +1 -0
- package/build/lib/config-file.js +1 -1
- package/build/lib/config.d.ts +40 -0
- package/build/lib/config.d.ts.map +1 -0
- package/build/lib/config.js +2 -2
- package/build/lib/constants.d.ts +48 -0
- package/build/lib/constants.d.ts.map +1 -0
- package/build/lib/constants.js +1 -1
- package/build/lib/extension/driver-config.d.ts +84 -0
- package/build/lib/extension/driver-config.d.ts.map +1 -0
- package/build/lib/extension/driver-config.js +1 -1
- package/build/lib/extension/extension-config.d.ts +170 -0
- package/build/lib/extension/extension-config.d.ts.map +1 -0
- package/build/lib/extension/extension-config.js +2 -2
- package/build/lib/extension/index.d.ts +39 -0
- package/build/lib/extension/index.d.ts.map +1 -0
- package/build/lib/extension/index.js +1 -1
- package/build/lib/extension/manifest.d.ts +174 -0
- package/build/lib/extension/manifest.d.ts.map +1 -0
- package/build/lib/extension/manifest.js +1 -1
- package/build/lib/extension/package-changed.d.ts +11 -0
- package/build/lib/extension/package-changed.d.ts.map +1 -0
- package/build/lib/extension/package-changed.js +1 -1
- package/build/lib/extension/plugin-config.d.ts +62 -0
- package/build/lib/extension/plugin-config.d.ts.map +1 -0
- package/build/lib/extension/plugin-config.js +1 -1
- package/build/lib/grid-register.d.ts +10 -0
- package/build/lib/grid-register.d.ts.map +1 -0
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logsink.d.ts +4 -0
- package/build/lib/logsink.d.ts.map +1 -0
- package/build/lib/logsink.js +1 -1
- package/build/lib/main.d.ts +51 -0
- package/build/lib/main.d.ts.map +1 -0
- package/build/lib/main.js +1 -1
- package/build/lib/schema/arg-spec.d.ts +143 -0
- package/build/lib/schema/arg-spec.d.ts.map +1 -0
- package/build/lib/schema/arg-spec.js +1 -1
- package/build/lib/schema/cli-args.d.ts +19 -0
- package/build/lib/schema/cli-args.d.ts.map +1 -0
- package/build/lib/schema/cli-args.js +1 -1
- package/build/lib/schema/cli-transformers.d.ts +5 -0
- package/build/lib/schema/cli-transformers.d.ts.map +1 -0
- package/build/lib/schema/cli-transformers.js +1 -1
- package/build/lib/schema/index.d.ts +3 -0
- package/build/lib/schema/index.d.ts.map +1 -0
- package/build/lib/schema/keywords.d.ts +24 -0
- package/build/lib/schema/keywords.d.ts.map +1 -0
- package/build/lib/schema/keywords.js +1 -1
- package/build/lib/schema/schema.d.ts +259 -0
- package/build/lib/schema/schema.d.ts.map +1 -0
- package/build/lib/schema/schema.js +3 -3
- package/build/lib/utils.d.ts +66 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.js +6 -4
- package/build/tsconfig.tsbuildinfo +1 -0
- package/lib/appium.js +163 -81
- package/lib/cli/args.js +1 -2
- package/lib/cli/driver-command.js +11 -8
- package/lib/cli/extension-command.js +129 -80
- package/lib/cli/extension.js +13 -3
- package/lib/cli/parser.js +1 -2
- package/lib/cli/plugin-command.js +16 -6
- package/lib/cli/utils.js +1 -1
- package/lib/config-file.js +3 -4
- package/lib/config.js +12 -8
- package/lib/constants.js +0 -1
- package/lib/extension/driver-config.js +31 -12
- package/lib/extension/extension-config.js +21 -22
- package/lib/extension/index.js +1 -2
- package/lib/extension/manifest.js +23 -127
- package/lib/extension/package-changed.js +0 -1
- package/lib/extension/plugin-config.js +9 -7
- package/lib/logsink.js +4 -0
- package/lib/main.js +9 -10
- package/lib/schema/arg-spec.js +10 -6
- package/lib/schema/cli-args.js +0 -1
- package/lib/schema/cli-transformers.js +0 -1
- package/lib/schema/keywords.js +0 -1
- package/lib/schema/schema.js +2 -3
- package/lib/utils.js +49 -16
- package/package.json +12 -14
- package/types/appium-manifest.d.ts +61 -0
- package/types/cli.d.ts +134 -0
- package/types/extension.d.ts +56 -0
- package/types/external-manifest.d.ts +58 -0
- package/types/index.d.ts +7 -0
- package/build/lib/appium-config.schema.json +0 -278
- package/build/lib/schema/appium-config-schema.js +0 -251
- package/lib/schema/appium-config-schema.js +0 -287
- package/types/appium-config.d.ts +0 -197
- package/types/types.d.ts +0 -245
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
// @ts-check
|
|
2
1
|
/* eslint-disable no-console */
|
|
3
2
|
|
|
4
3
|
import _ from 'lodash';
|
|
5
|
-
import
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { npm, fs, util, env } from '@appium/support';
|
|
6
6
|
import { log, spinWith, RingBuffer } from './utils';
|
|
7
7
|
import { SubProcess } from 'teen_process';
|
|
8
8
|
import { INSTALL_TYPE_NPM, INSTALL_TYPE_GIT, INSTALL_TYPE_GITHUB,
|
|
9
9
|
INSTALL_TYPE_LOCAL } from '../extension/extension-config';
|
|
10
|
+
import { packageDidChange } from '../extension/package-changed';
|
|
10
11
|
|
|
11
12
|
const UPDATE_ALL = 'installed';
|
|
12
13
|
|
|
@@ -16,7 +17,7 @@ class NoUpdatesAvailableError extends Error {}
|
|
|
16
17
|
/**
|
|
17
18
|
* @template {ExtensionType} ExtType
|
|
18
19
|
*/
|
|
19
|
-
|
|
20
|
+
class ExtensionCommand {
|
|
20
21
|
/**
|
|
21
22
|
* This is the `DriverConfig` or `PluginConfig`, depending on `ExtType`.
|
|
22
23
|
* @type {ExtensionConfig<ExtType>}
|
|
@@ -25,7 +26,7 @@ export default class ExtensionCommand {
|
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* {@linkcode Record} of official plugins or drivers.
|
|
28
|
-
* @type {ExtType
|
|
29
|
+
* @type {KnownExtensions<ExtType>}
|
|
29
30
|
*/
|
|
30
31
|
knownExtensions;
|
|
31
32
|
|
|
@@ -59,7 +60,7 @@ export default class ExtensionCommand {
|
|
|
59
60
|
*/
|
|
60
61
|
async execute (args) {
|
|
61
62
|
const cmd = args[`${this.type}Command`];
|
|
62
|
-
if (!_.isFunction(
|
|
63
|
+
if (!_.isFunction(this[cmd])) {
|
|
63
64
|
throw new Error(`Cannot handle ${this.type} command ${cmd}`);
|
|
64
65
|
}
|
|
65
66
|
const executeCmd = this[cmd].bind(this);
|
|
@@ -91,7 +92,12 @@ export default class ExtensionCommand {
|
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
return acc;
|
|
94
|
-
},
|
|
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
|
+
*/({}));
|
|
95
101
|
|
|
96
102
|
// if we want to show whether updates are available, put that behind a spinner
|
|
97
103
|
await spinWith(this.isJsonOutput, lsMsg, async () => {
|
|
@@ -111,16 +117,18 @@ export default class ExtensionCommand {
|
|
|
111
117
|
}
|
|
112
118
|
});
|
|
113
119
|
|
|
120
|
+
const listData = /** @type {ExtensionListData} */(exts);
|
|
121
|
+
|
|
114
122
|
// if we're just getting the data, short circuit return here since we don't need to do any
|
|
115
123
|
// formatting logic
|
|
116
124
|
if (this.isJsonOutput) {
|
|
117
|
-
return
|
|
125
|
+
return listData;
|
|
118
126
|
}
|
|
119
127
|
|
|
120
128
|
for (const [
|
|
121
129
|
name,
|
|
122
130
|
data
|
|
123
|
-
] of _.toPairs(
|
|
131
|
+
] of _.toPairs(listData)) {
|
|
124
132
|
let installTxt = ' [not installed]'.grey;
|
|
125
133
|
let updateTxt = '';
|
|
126
134
|
let upToDateTxt = '';
|
|
@@ -157,7 +165,7 @@ export default class ExtensionCommand {
|
|
|
157
165
|
console.log(`- ${name.yellow}${installTxt}${updateTxt}${upToDateTxt}${unsafeUpdateTxt}`);
|
|
158
166
|
}
|
|
159
167
|
|
|
160
|
-
return
|
|
168
|
+
return listData;
|
|
161
169
|
}
|
|
162
170
|
|
|
163
171
|
/**
|
|
@@ -166,8 +174,7 @@ export default class ExtensionCommand {
|
|
|
166
174
|
* @param {InstallArgs} args
|
|
167
175
|
* @return {Promise<ExtRecord<ExtType>>} map of all installed extension names to extension data
|
|
168
176
|
*/
|
|
169
|
-
async
|
|
170
|
-
/** @type {ExtData<ExtType>} */
|
|
177
|
+
async _install ({ext, installType, packageName}) {
|
|
171
178
|
let extData;
|
|
172
179
|
let installSpec = ext;
|
|
173
180
|
|
|
@@ -179,14 +186,7 @@ export default class ExtensionCommand {
|
|
|
179
186
|
throw new Error(`When using --source=${installType}, must also use --package`);
|
|
180
187
|
}
|
|
181
188
|
|
|
182
|
-
if (installType ===
|
|
183
|
-
const msg = `Linking ${this.type} from local path into ${this.config.appiumHome}`;
|
|
184
|
-
const pkgJsonData = await spinWith(this.isJsonOutput, msg, async () => (
|
|
185
|
-
await npm.linkPackage(this.config.appiumHome, installSpec))
|
|
186
|
-
);
|
|
187
|
-
extData = this.getExtensionFields(pkgJsonData);
|
|
188
|
-
log(this.isJsonOutput, `Successfully linked ${extData.pkgName} into ${this.config.appiumHome}`);
|
|
189
|
-
} else if (installType === INSTALL_TYPE_GITHUB) {
|
|
189
|
+
if (installType === INSTALL_TYPE_GITHUB) {
|
|
190
190
|
if (installSpec.split('/').length !== 2) {
|
|
191
191
|
throw new Error(`Github ${this.type} spec ${installSpec} appeared to be invalid; ` +
|
|
192
192
|
'it should be of the form <org>/<repo>');
|
|
@@ -198,40 +198,44 @@ export default class ExtensionCommand {
|
|
|
198
198
|
installSpec = installSpec.replace(/\.git$/, '');
|
|
199
199
|
extData = await this.installViaNpm({ext: installSpec, pkgName: /** @type {string} */(packageName)});
|
|
200
200
|
} else {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
// sign, so check for that. We also need to be careful that package names themselves can
|
|
205
|
-
// contain the '@' symbol, as in `npm install @appium/fake-driver@1.2.0`
|
|
206
|
-
let name, pkgVer;
|
|
207
|
-
const splits = installSpec.split('@');
|
|
208
|
-
if (installSpec[0] === '@') {
|
|
209
|
-
// this is the case where we have an npm org included in the package name
|
|
210
|
-
[name, pkgVer] = [`@${splits[1]}`, splits[2]];
|
|
201
|
+
let pkgName, pkgVer;
|
|
202
|
+
if (installType === INSTALL_TYPE_LOCAL) {
|
|
203
|
+
pkgName = path.isAbsolute(installSpec) ? installSpec : path.resolve(installSpec);
|
|
211
204
|
} else {
|
|
212
|
-
// this
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
205
|
+
// at this point we have either an npm package or an appium verified extension
|
|
206
|
+
// name or a local path. both of which will be installed via npm.
|
|
207
|
+
// extensions installed via npm can include versions or tags after the '@'
|
|
208
|
+
// sign, so check for that. We also need to be careful that package names themselves can
|
|
209
|
+
// contain the '@' symbol, as in `npm install @appium/fake-driver@1.2.0`
|
|
210
|
+
let name;
|
|
211
|
+
const splits = installSpec.split('@');
|
|
212
|
+
if (installSpec[0] === '@') {
|
|
213
|
+
// this is the case where we have an npm org included in the package name
|
|
214
|
+
[name, pkgVer] = [`@${splits[1]}`, splits[2]];
|
|
215
|
+
} else {
|
|
216
|
+
// this is the case without an npm org
|
|
217
|
+
[name, pkgVer] = splits;
|
|
218
|
+
}
|
|
216
219
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
220
|
+
if (installType === INSTALL_TYPE_NPM) {
|
|
221
|
+
// if we're installing a named package from npm, we don't need to check
|
|
222
|
+
// against the appium extension list; just use the installSpec as is
|
|
223
|
+
pkgName = name;
|
|
224
|
+
} else {
|
|
225
|
+
// if we're installing a named appium driver (like 'xcuitest') we need to
|
|
226
|
+
// dereference the actual npm package ('appiupm-xcuitest-driver'), so
|
|
227
|
+
// check it exists and get the correct package
|
|
228
|
+
const knownNames = Object.keys(this.knownExtensions);
|
|
229
|
+
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)}`;
|
|
232
|
+
throw new Error(msg);
|
|
233
|
+
}
|
|
234
|
+
pkgName = this.knownExtensions[name];
|
|
235
|
+
// given that we'll use the install type in the driver json, store it as
|
|
236
|
+
// 'npm' now
|
|
237
|
+
installType = INSTALL_TYPE_NPM;
|
|
230
238
|
}
|
|
231
|
-
pkgName = this.knownExtensions[name];
|
|
232
|
-
// given that we'll use the install type in the driver json, store it as
|
|
233
|
-
// 'npm' now
|
|
234
|
-
installType = INSTALL_TYPE_NPM;
|
|
235
239
|
}
|
|
236
240
|
|
|
237
241
|
extData = await this.installViaNpm({ext, pkgName, pkgVer});
|
|
@@ -246,9 +250,13 @@ export default class ExtensionCommand {
|
|
|
246
250
|
`installed ${this.type}s with 'appium ${this.type} list --installed'.`);
|
|
247
251
|
}
|
|
248
252
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
253
|
+
const extManifest = {...extData, installType, installSpec};
|
|
254
|
+
await this.config.addExtension(extName, extManifest);
|
|
255
|
+
|
|
256
|
+
// update the if we've changed the local `package.json`
|
|
257
|
+
if (await env.hasAppiumDependency(this.config.appiumHome)) {
|
|
258
|
+
await packageDidChange(this.config.appiumHome);
|
|
259
|
+
}
|
|
252
260
|
|
|
253
261
|
// log info for the user
|
|
254
262
|
log(this.isJsonOutput, this.getPostInstallText({extName, extData}));
|
|
@@ -260,7 +268,6 @@ export default class ExtensionCommand {
|
|
|
260
268
|
* Install an extension via NPM
|
|
261
269
|
*
|
|
262
270
|
* @param {InstallViaNpmArgs} args
|
|
263
|
-
* @returns {Promise<ExtData<ExtType>>}
|
|
264
271
|
*/
|
|
265
272
|
async installViaNpm ({ext, pkgName, pkgVer}) {
|
|
266
273
|
const npmSpec = `${pkgName}${pkgVer ? '@' + pkgVer : ''}`;
|
|
@@ -296,8 +303,9 @@ export default class ExtensionCommand {
|
|
|
296
303
|
* load as the main driver class, or to be able to detect incompatibilities between driver and
|
|
297
304
|
* appium versions.
|
|
298
305
|
*
|
|
299
|
-
* @param {
|
|
306
|
+
* @param {ExtPackageJson<ExtType>} pkgJsonData - the package.json data for a driver module, as if it had been
|
|
300
307
|
* straightforwardly 'require'd
|
|
308
|
+
* @returns {ExtensionFields<ExtType>}
|
|
301
309
|
*/
|
|
302
310
|
getExtensionFields (pkgJsonData) {
|
|
303
311
|
if (!pkgJsonData.appium) {
|
|
@@ -306,8 +314,9 @@ export default class ExtensionCommand {
|
|
|
306
314
|
}
|
|
307
315
|
const {appium, name, version} = pkgJsonData;
|
|
308
316
|
this.validateExtensionFields(appium);
|
|
309
|
-
|
|
310
|
-
|
|
317
|
+
/** @type {unknown} */
|
|
318
|
+
const result = {...appium, pkgName: name, version};
|
|
319
|
+
return /** @type {ExtensionFields<ExtType>} */(result);
|
|
311
320
|
}
|
|
312
321
|
|
|
313
322
|
/**
|
|
@@ -315,19 +324,20 @@ export default class ExtensionCommand {
|
|
|
315
324
|
* presence and form of those fields on the package.json data, throwing an error if anything is
|
|
316
325
|
* amiss.
|
|
317
326
|
*
|
|
318
|
-
* @param {
|
|
327
|
+
* @param {ExtMetadata<ExtType>} appiumPkgData - the data in the "appium" field of package.json for an extension
|
|
319
328
|
*/
|
|
320
329
|
// eslint-disable-next-line no-unused-vars
|
|
321
330
|
validateExtensionFields (appiumPkgData) {
|
|
322
331
|
throw new Error('Must be implemented in final class');
|
|
323
332
|
}
|
|
333
|
+
|
|
324
334
|
/**
|
|
325
335
|
* Uninstall an extension
|
|
326
336
|
*
|
|
327
337
|
* @param {UninstallOpts} opts
|
|
328
338
|
* @return {Promise<ExtRecord<ExtType>>} map of all installed extension names to extension data
|
|
329
339
|
*/
|
|
330
|
-
async
|
|
340
|
+
async _uninstall ({ext}) {
|
|
331
341
|
if (!this.config.isInstalled(ext)) {
|
|
332
342
|
throw new Error(`Can't uninstall ${this.type} '${ext}'; it is not installed`);
|
|
333
343
|
}
|
|
@@ -347,7 +357,7 @@ export default class ExtensionCommand {
|
|
|
347
357
|
* @param {ExtensionUpdateOpts} updateSpec
|
|
348
358
|
* @return {Promise<ExtensionUpdateResult>}
|
|
349
359
|
*/
|
|
350
|
-
async
|
|
360
|
+
async _update ({ext, unsafe}) {
|
|
351
361
|
const shouldUpdateAll = ext === UPDATE_ALL;
|
|
352
362
|
// if we're specifically requesting an update for an extension, make sure it's installed
|
|
353
363
|
if (!shouldUpdateAll && !this.config.isInstalled(ext)) {
|
|
@@ -450,6 +460,7 @@ export default class ExtensionCommand {
|
|
|
450
460
|
*
|
|
451
461
|
* @param {string} ext - name of extension to update
|
|
452
462
|
* @param {string} version - version string identifier to update extension to
|
|
463
|
+
* @returns {Promise<void>}
|
|
453
464
|
*/
|
|
454
465
|
async updateExtension (ext, version) {
|
|
455
466
|
const {pkgName} = this.config.installedExtensions[ext];
|
|
@@ -470,7 +481,7 @@ export default class ExtensionCommand {
|
|
|
470
481
|
* @param {RunOptions} opts
|
|
471
482
|
* @return {Promise<RunOutput>}
|
|
472
483
|
*/
|
|
473
|
-
async
|
|
484
|
+
async _run ({ext, scriptName}) {
|
|
474
485
|
if (!_.has(this.config.installedExtensions, ext)) {
|
|
475
486
|
throw new Error(`please install the ${this.type} first`);
|
|
476
487
|
}
|
|
@@ -519,10 +530,8 @@ export default class ExtensionCommand {
|
|
|
519
530
|
}
|
|
520
531
|
}
|
|
521
532
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
* @typedef {import('../extension/extension-config').ExtensionConfig<ExtType>} ExtensionConfig
|
|
525
|
-
*/
|
|
533
|
+
export default ExtensionCommand;
|
|
534
|
+
export {ExtensionCommand};
|
|
526
535
|
|
|
527
536
|
/**
|
|
528
537
|
* Options for the {@linkcode ExtensionCommand} constructor
|
|
@@ -537,39 +546,68 @@ export default class ExtensionCommand {
|
|
|
537
546
|
*
|
|
538
547
|
* @typedef ExtensionMetadata
|
|
539
548
|
* @property {boolean} installed - If `true`, the extension is installed
|
|
540
|
-
* @property {string
|
|
541
|
-
* @property {string
|
|
542
|
-
* @property {boolean}
|
|
549
|
+
* @property {string?} updateVersion - If the extension is installed, the version it can be updated to
|
|
550
|
+
* @property {string?} unsafeUpdateVersion - Same as above, but a major version bump
|
|
551
|
+
* @property {boolean} upToDate - If the extension is installed and the latest
|
|
552
|
+
*/
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* @typedef {import('../../types').ExtensionType} ExtensionType
|
|
556
|
+
* @typedef {import('../../types').DriverType} DriverType
|
|
557
|
+
* @typedef {import('../../types').PluginType} PluginType
|
|
543
558
|
*/
|
|
544
559
|
|
|
545
560
|
/**
|
|
546
|
-
* @
|
|
561
|
+
* @template {ExtensionType} ExtType
|
|
562
|
+
* @typedef {import('../../types/appium-manifest').ExtRecord<ExtType>} ExtRecord
|
|
547
563
|
*/
|
|
548
564
|
|
|
549
565
|
/**
|
|
550
566
|
* @template {ExtensionType} ExtType
|
|
551
|
-
* @typedef {import('../extension/
|
|
567
|
+
* @typedef {import('../extension/extension-config').ExtensionConfig<ExtType>} ExtensionConfig
|
|
552
568
|
*/
|
|
553
569
|
|
|
554
570
|
/**
|
|
555
571
|
* @template {ExtensionType} ExtType
|
|
556
|
-
* @typedef {import('
|
|
572
|
+
* @typedef {import('../../types/external-manifest').ExtMetadata<ExtType>} ExtMetadata
|
|
573
|
+
*/
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* @template {ExtensionType} ExtType
|
|
577
|
+
* @typedef {import('../../types/appium-manifest').ExtManifest<ExtType>} ExtManifest
|
|
578
|
+
*/
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* @template {ExtensionType} ExtType
|
|
582
|
+
* @typedef {import('../../types/external-manifest').ExtPackageJson<ExtType>} ExtPackageJson
|
|
583
|
+
*/
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Possible return value for {@linkcode ExtensionCommand.list}
|
|
587
|
+
* @typedef UninstalledExtensionListData
|
|
588
|
+
* @property {string} pkgName
|
|
589
|
+
* @property {false} installed
|
|
590
|
+
*/
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Possible return value for {@linkcode ExtensionCommand.list}
|
|
594
|
+
* @typedef {import('../../types/appium-manifest').InternalMetadata & ExtensionMetadata} InstalledExtensionListData
|
|
557
595
|
*/
|
|
558
596
|
|
|
559
597
|
/**
|
|
560
598
|
* Return value of {@linkcode ExtensionCommand.list}.
|
|
561
|
-
* @typedef {Record<string,
|
|
599
|
+
* @typedef {Record<string,InstalledExtensionListData|UninstalledExtensionListData>} ExtensionListData
|
|
562
600
|
*/
|
|
563
601
|
|
|
564
602
|
/**
|
|
565
|
-
* Options for {@linkcode ExtensionCommand.
|
|
603
|
+
* Options for {@linkcode ExtensionCommand._run}.
|
|
566
604
|
* @typedef RunOptions
|
|
567
605
|
* @property {string} ext - name of the extension to run a script from
|
|
568
606
|
* @property {string} scriptName - name of the script to run
|
|
569
607
|
*/
|
|
570
608
|
|
|
571
609
|
/**
|
|
572
|
-
* Return value of {@linkcode ExtensionCommand.
|
|
610
|
+
* Return value of {@linkcode ExtensionCommand._run}
|
|
573
611
|
*
|
|
574
612
|
* @typedef RunOutput
|
|
575
613
|
* @property {string} [error] - error message if script ran unsuccessfully, otherwise undefined
|
|
@@ -577,28 +615,28 @@ export default class ExtensionCommand {
|
|
|
577
615
|
*/
|
|
578
616
|
|
|
579
617
|
/**
|
|
580
|
-
* Options for {@linkcode ExtensionCommand.
|
|
618
|
+
* Options for {@linkcode ExtensionCommand._update}.
|
|
581
619
|
* @typedef ExtensionUpdateOpts
|
|
582
620
|
* @property {string} ext - the name of the extension to update
|
|
583
621
|
* @property {boolean} unsafe - if true, will perform unsafe updates past major revision boundaries
|
|
584
622
|
*/
|
|
585
623
|
|
|
586
624
|
/**
|
|
587
|
-
* Return value of {@linkcode ExtensionCommand.
|
|
625
|
+
* Return value of {@linkcode ExtensionCommand._update}.
|
|
588
626
|
* @typedef ExtensionUpdateResult
|
|
589
627
|
* @property {Record<string,Error>} errors - map of ext names to error objects
|
|
590
628
|
* @property {Record<string,UpdateReport>} updates - map of ext names to {@linkcode UpdateReport}s
|
|
591
629
|
*/
|
|
592
630
|
|
|
593
631
|
/**
|
|
594
|
-
* Part of result of {@linkcode ExtensionCommand.
|
|
632
|
+
* Part of result of {@linkcode ExtensionCommand._update}.
|
|
595
633
|
* @typedef UpdateReport
|
|
596
634
|
* @property {string} from - version the extension was updated from
|
|
597
635
|
* @property {string} to - version the extension was updated to
|
|
598
636
|
*/
|
|
599
637
|
|
|
600
638
|
/**
|
|
601
|
-
* Options for {@linkcode ExtensionCommand.
|
|
639
|
+
* Options for {@linkcode ExtensionCommand._uninstall}.
|
|
602
640
|
* @typedef UninstallOpts
|
|
603
641
|
* @property {string} ext - the name or spec of an extension to uninstall
|
|
604
642
|
*/
|
|
@@ -627,9 +665,20 @@ export default class ExtensionCommand {
|
|
|
627
665
|
*/
|
|
628
666
|
|
|
629
667
|
/**
|
|
630
|
-
* Options for {@linkcode ExtensionCommand.
|
|
668
|
+
* Options for {@linkcode ExtensionCommand._install}
|
|
631
669
|
* @typedef InstallArgs
|
|
632
670
|
* @property {string} ext - the name or spec of an extension to install
|
|
633
|
-
* @property {import('
|
|
671
|
+
* @property {import('../../types/appium-manifest').InstallType} installType - how to install this extension. One of the INSTALL_TYPES
|
|
634
672
|
* @property {string} [packageName] - for git/github installs, the extension node package name
|
|
635
673
|
*/
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Returned by {@linkcode ExtensionCommand.getExtensionFields}
|
|
677
|
+
* @template {ExtensionType} ExtType
|
|
678
|
+
* @typedef {ExtMetadata<ExtType> & { pkgName: string, version: string } & import('../../types/external-manifest').CommonMetadata} ExtensionFields
|
|
679
|
+
*/
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* @template {ExtensionType} ExtType
|
|
683
|
+
* @typedef {ExtType extends DriverType ? typeof import('../constants').KNOWN_DRIVERS : ExtType extends PluginType ? typeof import('../constants').KNOWN_PLUGINS : never} KnownExtensions
|
|
684
|
+
*/
|
package/lib/cli/extension.js
CHANGED
|
@@ -2,16 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
import DriverCommand from './driver-command';
|
|
4
4
|
import PluginCommand from './plugin-command';
|
|
5
|
-
import { DRIVER_TYPE } from '../constants';
|
|
5
|
+
import { DRIVER_TYPE, PLUGIN_TYPE } from '../constants';
|
|
6
6
|
import { errAndQuit, log, JSON_SPACES } from './utils';
|
|
7
7
|
|
|
8
|
+
const commandClasses = Object.freeze(/** @type {const} */({
|
|
9
|
+
[DRIVER_TYPE]: DriverCommand,
|
|
10
|
+
[PLUGIN_TYPE]: PluginCommand
|
|
11
|
+
}));
|
|
12
|
+
|
|
8
13
|
/**
|
|
9
14
|
* Run a subcommand of the 'appium driver' type. Each subcommand has its own set of arguments which
|
|
10
15
|
* can be represented as a JS object.
|
|
11
16
|
*
|
|
12
17
|
* @param {Object} args - JS object where the key is the parameter name (as defined in
|
|
13
18
|
* driver-parser.js)
|
|
14
|
-
* @template {ExtensionType} ExtType
|
|
19
|
+
* @template {import('../extension/manifest').ExtensionType} ExtType
|
|
15
20
|
* @param {import('../extension/extension-config').ExtensionConfig<ExtType>} configObject - Extension config object
|
|
16
21
|
*/
|
|
17
22
|
async function runExtensionCommand (args, configObject) {
|
|
@@ -30,7 +35,7 @@ async function runExtensionCommand (args, configObject) {
|
|
|
30
35
|
const logFn = (msg) => log(json, msg);
|
|
31
36
|
let config = configObject;
|
|
32
37
|
config.log = logFn;
|
|
33
|
-
const CommandClass = type
|
|
38
|
+
const CommandClass = /** @type {ExtCommand<ExtType>} */(commandClasses[type]);
|
|
34
39
|
const cmd = new CommandClass({config, json});
|
|
35
40
|
try {
|
|
36
41
|
jsonResult = await cmd.execute(args);
|
|
@@ -53,3 +58,8 @@ async function runExtensionCommand (args, configObject) {
|
|
|
53
58
|
export {
|
|
54
59
|
runExtensionCommand,
|
|
55
60
|
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @template {import('../../types').ExtensionType} ExtType
|
|
64
|
+
* @typedef {ExtType extends import('../../types').DriverType ? import('@appium/types').Class<DriverCommand> : ExtType extends import('../../types').PluginType ? import('@appium/types').Class<PluginCommand> : never} ExtCommand
|
|
65
|
+
*/
|
package/lib/cli/parser.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-check
|
|
2
1
|
|
|
3
2
|
import { fs } from '@appium/support';
|
|
4
3
|
import { ArgumentParser } from 'argparse';
|
|
@@ -101,7 +100,7 @@ class ArgParser {
|
|
|
101
100
|
*
|
|
102
101
|
* `ArgParser.prototype.parse_args` is an alias of this method.
|
|
103
102
|
* @param {string[]} [args] - Array of arguments, ostensibly from `process.argv`. Gathers args from `process.argv` if not provided.
|
|
104
|
-
* @returns {import('../../types/
|
|
103
|
+
* @returns {import('../../types/cli').ParsedArgs} - The parsed arguments
|
|
105
104
|
*/
|
|
106
105
|
parseArgs (args = process.argv.slice(2)) {
|
|
107
106
|
if (!NON_SERVER_ARGS.has(args[0])) {
|
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import ExtensionCommand from './extension-command';
|
|
3
|
-
import {
|
|
3
|
+
import { KNOWN_PLUGINS } from '../constants';
|
|
4
4
|
|
|
5
5
|
const REQ_PLUGIN_FIELDS = ['pluginName', 'mainClass'];
|
|
6
6
|
|
|
7
7
|
export default class PluginCommand extends ExtensionCommand {
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {PluginCommandOptions} opts
|
|
12
|
+
*/
|
|
9
13
|
constructor ({config, json}) {
|
|
10
|
-
super({config, json
|
|
14
|
+
super({config, json});
|
|
11
15
|
this.knownExtensions = KNOWN_PLUGINS;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
async install ({plugin, installType, packageName}) {
|
|
15
|
-
return await super.
|
|
19
|
+
return await super._install({ext: plugin, installType, packageName});
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
async uninstall ({plugin}) {
|
|
19
|
-
return await super.
|
|
23
|
+
return await super._uninstall({ext: plugin});
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
async update ({plugin, unsafe}) {
|
|
23
|
-
return await super.
|
|
27
|
+
return await super._update({ext: plugin, unsafe});
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
async run ({plugin, scriptName}) {
|
|
27
|
-
return await super.
|
|
31
|
+
return await super._run({ext: plugin, scriptName});
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
getPostInstallText ({extName, extData}) {
|
|
@@ -44,3 +48,9 @@ export default class PluginCommand extends ExtensionCommand {
|
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @typedef PluginCommandOptions
|
|
54
|
+
* @property {import('../extension/extension-config').ExtensionConfig<import('../extension/manifest').PluginType>} config
|
|
55
|
+
* @property {boolean} json
|
|
56
|
+
*/
|
package/lib/cli/utils.js
CHANGED
|
@@ -7,7 +7,7 @@ const JSON_SPACES = 4;
|
|
|
7
7
|
/***
|
|
8
8
|
* Log an error to the console and exit the process.
|
|
9
9
|
* @param {boolean} json - whether we should log json or text
|
|
10
|
-
* @param {
|
|
10
|
+
* @param {any} msg - error message, object, Error instance, etc.
|
|
11
11
|
*/
|
|
12
12
|
function errAndQuit (json, msg) {
|
|
13
13
|
if (json) {
|
package/lib/config-file.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-check
|
|
2
1
|
|
|
3
2
|
import betterAjvErrors from '@sidvind/better-ajv-errors';
|
|
4
3
|
import { lilconfig } from 'lilconfig';
|
|
@@ -186,7 +185,7 @@ export function normalizeConfig (config) {
|
|
|
186
185
|
* @property {string} [filepath] - The path to the config file, if found
|
|
187
186
|
* @property {boolean} [isEmpty] - If `true`, the config file exists but is empty
|
|
188
187
|
* @property {NormalizedAppiumConfig} [config] - The parsed configuration
|
|
189
|
-
* @property {string|
|
|
188
|
+
* @property {string|import('@sidvind/better-ajv-errors').IOutputError[]} [reason] - Human-readable error messages and suggestions. If the `pretty` option is `true`, this will be a nice string to print.
|
|
190
189
|
*/
|
|
191
190
|
|
|
192
191
|
/**
|
|
@@ -202,12 +201,12 @@ export function normalizeConfig (config) {
|
|
|
202
201
|
|
|
203
202
|
/**
|
|
204
203
|
* The contents of an Appium config file. Generated from schema
|
|
205
|
-
* @typedef {import('
|
|
204
|
+
* @typedef {import('@appium/types').AppiumConfig} AppiumConfig
|
|
206
205
|
*/
|
|
207
206
|
|
|
208
207
|
/**
|
|
209
208
|
* The contents of an Appium config file with camelcased property names (and using `appiumCliDest` value if present). Generated from {@link AppiumConfig}
|
|
210
|
-
* @typedef {import('
|
|
209
|
+
* @typedef {import('@appium/types').NormalizedAppiumConfig} NormalizedAppiumConfig
|
|
211
210
|
*/
|
|
212
211
|
|
|
213
212
|
/**
|
package/lib/config.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
1
|
/* eslint-disable no-console */
|
|
4
2
|
import _ from 'lodash';
|
|
5
3
|
import { system, fs } from '@appium/support';
|
|
@@ -19,6 +17,9 @@ const GIT_META_ROOT = '.git';
|
|
|
19
17
|
const GIT_BINARY = `git${system.isWindows() ? '.exe' : ''}`;
|
|
20
18
|
const GITHUB_API = 'https://api.github.com/repos/appium/appium';
|
|
21
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @type {import('../types/cli').BuildInfo}
|
|
22
|
+
*/
|
|
22
23
|
const BUILD_INFO = {
|
|
23
24
|
version: APPIUM_VER,
|
|
24
25
|
};
|
|
@@ -34,7 +35,7 @@ async function updateBuildInfo (useGithubApiFallback = false) {
|
|
|
34
35
|
}
|
|
35
36
|
BUILD_INFO['git-sha'] = sha;
|
|
36
37
|
const built = await getGitTimestamp(sha, useGithubApiFallback);
|
|
37
|
-
if (
|
|
38
|
+
if (built) {
|
|
38
39
|
BUILD_INFO.built = built;
|
|
39
40
|
}
|
|
40
41
|
}
|
|
@@ -85,7 +86,7 @@ async function getGitRev (useGithubApiFallback = false) {
|
|
|
85
86
|
/**
|
|
86
87
|
* @param {string} commitSha
|
|
87
88
|
* @param {boolean} [useGithubApiFallback]
|
|
88
|
-
* @returns {Promise<
|
|
89
|
+
* @returns {Promise<string?>}
|
|
89
90
|
*/
|
|
90
91
|
async function getGitTimestamp (commitSha, useGithubApiFallback = false) {
|
|
91
92
|
const gitRoot = await findGitRoot();
|
|
@@ -121,10 +122,11 @@ async function getGitTimestamp (commitSha, useGithubApiFallback = false) {
|
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
/**
|
|
124
|
-
*
|
|
125
|
+
* Mutable object containing Appium build information. By default it
|
|
125
126
|
* only contains the Appium version, but is updated with the build timestamp
|
|
126
127
|
* and git commit hash asynchronously as soon as `updateBuildInfo` is called
|
|
127
128
|
* and succeeds.
|
|
129
|
+
* @returns {import('../types/cli').BuildInfo}
|
|
128
130
|
*/
|
|
129
131
|
function getBuildInfo () {
|
|
130
132
|
return BUILD_INFO;
|
|
@@ -166,7 +168,7 @@ function getNonDefaultServerArgs (parsedArgs) {
|
|
|
166
168
|
* Flattens parsed args into a single level object for comparison with
|
|
167
169
|
* flattened defaults across server args and extension args.
|
|
168
170
|
* @param {ParsedArgs} args
|
|
169
|
-
* @returns {Record<string, { value: any, argSpec:
|
|
171
|
+
* @returns {Record<string, { value: any, argSpec: ArgSpec }>}
|
|
170
172
|
*/
|
|
171
173
|
const flatten = (args) => {
|
|
172
174
|
const argSpecs = getAllArgSpecs();
|
|
@@ -175,7 +177,7 @@ function getNonDefaultServerArgs (parsedArgs) {
|
|
|
175
177
|
acc[argSpec.dest] = {value: _.get(args, argSpec.dest), argSpec};
|
|
176
178
|
}
|
|
177
179
|
return acc;
|
|
178
|
-
}, /** @type {Record<string, { value: any, argSpec:
|
|
180
|
+
}, /** @type {Record<string, { value: any, argSpec: ArgSpec }>} */({}));
|
|
179
181
|
|
|
180
182
|
return flattened;
|
|
181
183
|
};
|
|
@@ -304,5 +306,7 @@ export {
|
|
|
304
306
|
};
|
|
305
307
|
|
|
306
308
|
/**
|
|
307
|
-
* @typedef {import('../types/
|
|
309
|
+
* @typedef {import('../types/cli').ParsedArgs} ParsedArgs
|
|
310
|
+
* @typedef {import('./schema/arg-spec').ArgSpec} ArgSpec
|
|
308
311
|
*/
|
|
312
|
+
|
package/lib/constants.js
CHANGED