appium 3.3.0 → 3.3.1
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 +147 -205
- package/build/lib/appium.d.ts.map +1 -1
- package/build/lib/appium.js +169 -282
- package/build/lib/appium.js.map +1 -1
- package/build/lib/bidi-commands.d.ts.map +1 -1
- package/build/lib/bidi-commands.js +11 -11
- package/build/lib/bidi-commands.js.map +1 -1
- package/build/lib/bootstrap/appium-initializer.d.ts +21 -0
- package/build/lib/bootstrap/appium-initializer.d.ts.map +1 -0
- package/build/lib/bootstrap/appium-initializer.js +146 -0
- package/build/lib/bootstrap/appium-initializer.js.map +1 -0
- package/build/lib/bootstrap/appium-main-runner.d.ts +22 -0
- package/build/lib/bootstrap/appium-main-runner.d.ts.map +1 -0
- package/build/lib/bootstrap/appium-main-runner.js +109 -0
- package/build/lib/bootstrap/appium-main-runner.js.map +1 -0
- package/build/lib/bootstrap/config-file.d.ts +37 -0
- package/build/lib/bootstrap/config-file.d.ts.map +1 -0
- package/build/lib/{config-file.js → bootstrap/config-file.js} +9 -26
- package/build/lib/bootstrap/config-file.js.map +1 -0
- package/build/lib/bootstrap/grid-v3-register.d.ts +20 -0
- package/build/lib/bootstrap/grid-v3-register.d.ts.map +1 -0
- package/build/lib/{grid-register.js → bootstrap/grid-v3-register.js} +28 -13
- package/build/lib/bootstrap/grid-v3-register.js.map +1 -0
- package/build/lib/bootstrap/init-types.d.ts +16 -0
- package/build/lib/bootstrap/init-types.d.ts.map +1 -0
- package/build/lib/bootstrap/init-types.js +3 -0
- package/build/lib/bootstrap/init-types.js.map +1 -0
- package/build/lib/bootstrap/main-helpers.d.ts +55 -0
- package/build/lib/bootstrap/main-helpers.d.ts.map +1 -0
- package/build/lib/bootstrap/main-helpers.js +187 -0
- package/build/lib/bootstrap/main-helpers.js.map +1 -0
- package/build/lib/bootstrap/node-helpers.d.ts +32 -0
- package/build/lib/bootstrap/node-helpers.d.ts.map +1 -0
- package/build/lib/bootstrap/node-helpers.js +201 -0
- package/build/lib/bootstrap/node-helpers.js.map +1 -0
- package/build/lib/bootstrap/startup-config.d.ts +22 -0
- package/build/lib/bootstrap/startup-config.d.ts.map +1 -0
- package/build/lib/bootstrap/startup-config.js +111 -0
- package/build/lib/bootstrap/startup-config.js.map +1 -0
- package/build/lib/cli/args.d.ts.map +1 -1
- package/build/lib/cli/args.js +9 -9
- package/build/lib/cli/args.js.map +1 -1
- package/build/lib/cli/extension-command.d.ts +95 -95
- package/build/lib/cli/extension-command.d.ts.map +1 -1
- package/build/lib/cli/extension-command.js +18 -18
- package/build/lib/cli/extension-command.js.map +1 -1
- package/build/lib/cli/extension.d.ts +1 -1
- package/build/lib/cli/extension.d.ts.map +1 -1
- package/build/lib/cli/extension.js +5 -5
- package/build/lib/cli/extension.js.map +1 -1
- package/build/lib/cli/parser.d.ts +8 -8
- package/build/lib/cli/parser.d.ts.map +1 -1
- package/build/lib/cli/parser.js +49 -49
- package/build/lib/cli/parser.js.map +1 -1
- package/build/lib/cli/setup-command.js +6 -6
- package/build/lib/cli/setup-command.js.map +1 -1
- package/build/lib/cli/utils.d.ts +17 -17
- package/build/lib/cli/utils.d.ts.map +1 -1
- package/build/lib/cli/utils.js +29 -29
- package/build/lib/cli/utils.js.map +1 -1
- package/build/lib/doctor/doctor.d.ts +2 -2
- package/build/lib/doctor/doctor.d.ts.map +1 -1
- package/build/lib/doctor/doctor.js +6 -6
- package/build/lib/doctor/doctor.js.map +1 -1
- package/build/lib/extension/driver-config.d.ts +18 -77
- package/build/lib/extension/driver-config.d.ts.map +1 -1
- package/build/lib/extension/driver-config.js +37 -125
- package/build/lib/extension/driver-config.js.map +1 -1
- package/build/lib/extension/extension-config.d.ts +103 -210
- package/build/lib/extension/extension-config.d.ts.map +1 -1
- package/build/lib/extension/extension-config.js +180 -342
- package/build/lib/extension/extension-config.js.map +1 -1
- package/build/lib/extension/index.d.ts +12 -29
- package/build/lib/extension/index.d.ts.map +1 -1
- package/build/lib/extension/index.js +33 -75
- package/build/lib/extension/index.js.map +1 -1
- package/build/lib/extension/manifest-migrations.d.ts +3 -20
- package/build/lib/extension/manifest-migrations.d.ts.map +1 -1
- package/build/lib/extension/manifest-migrations.js +20 -101
- package/build/lib/extension/manifest-migrations.js.map +1 -1
- package/build/lib/extension/manifest.d.ts +61 -107
- package/build/lib/extension/manifest.d.ts.map +1 -1
- package/build/lib/extension/manifest.js +181 -356
- package/build/lib/extension/manifest.js.map +1 -1
- package/build/lib/extension/package-changed.d.ts +1 -3
- package/build/lib/extension/package-changed.d.ts.map +1 -1
- package/build/lib/extension/package-changed.js +8 -15
- package/build/lib/extension/package-changed.js.map +1 -1
- package/build/lib/extension/plugin-config.d.ts +10 -52
- package/build/lib/extension/plugin-config.d.ts.map +1 -1
- package/build/lib/extension/plugin-config.js +11 -63
- package/build/lib/extension/plugin-config.js.map +1 -1
- package/build/lib/helpers/build.d.ts +22 -0
- package/build/lib/helpers/build.d.ts.map +1 -0
- package/build/lib/helpers/build.js +109 -0
- package/build/lib/helpers/build.js.map +1 -0
- package/build/lib/helpers/capability.d.ts +38 -0
- package/build/lib/helpers/capability.d.ts.map +1 -0
- package/build/lib/helpers/capability.js +128 -0
- package/build/lib/helpers/capability.js.map +1 -0
- package/build/lib/helpers/network.d.ts +14 -0
- package/build/lib/helpers/network.d.ts.map +1 -0
- package/build/lib/helpers/network.js +35 -0
- package/build/lib/helpers/network.js.map +1 -0
- package/build/lib/insecure-features.js +6 -6
- package/build/lib/insecure-features.js.map +1 -1
- package/build/lib/inspector-commands.d.ts +6 -0
- package/build/lib/inspector-commands.d.ts.map +1 -1
- package/build/lib/inspector-commands.js +6 -0
- package/build/lib/inspector-commands.js.map +1 -1
- package/build/lib/logger.d.ts +2 -3
- package/build/lib/logger.d.ts.map +1 -1
- package/build/lib/logger.js +2 -3
- package/build/lib/logger.js.map +1 -1
- package/build/lib/main.d.ts +15 -58
- package/build/lib/main.d.ts.map +1 -1
- package/build/lib/main.js +25 -425
- package/build/lib/main.js.map +1 -1
- package/build/lib/schema/cli-args-guards.d.ts +34 -0
- package/build/lib/schema/cli-args-guards.d.ts.map +1 -0
- package/build/lib/schema/cli-args-guards.js +49 -0
- package/build/lib/schema/cli-args-guards.js.map +1 -0
- package/build/lib/schema/cli-args.js +2 -2
- package/build/lib/schema/cli-args.js.map +1 -1
- package/build/lib/schema/format-errors.d.ts +28 -0
- package/build/lib/schema/format-errors.d.ts.map +1 -0
- package/build/lib/schema/format-errors.js +29 -0
- package/build/lib/schema/format-errors.js.map +1 -0
- package/build/lib/schema/index.d.ts +2 -0
- package/build/lib/schema/index.d.ts.map +1 -1
- package/build/lib/schema/index.js +2 -0
- package/build/lib/schema/index.js.map +1 -1
- package/build/lib/schema/schema.d.ts +15 -15
- package/build/lib/schema/schema.d.ts.map +1 -1
- package/build/lib/schema/schema.js +37 -37
- package/build/lib/schema/schema.js.map +1 -1
- package/build/lib/utils.d.ts +0 -81
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +1 -248
- package/build/lib/utils.js.map +1 -1
- package/lib/{appium.js → appium.ts} +297 -341
- package/lib/bidi-commands.ts +10 -14
- package/lib/bootstrap/appium-initializer.ts +212 -0
- package/lib/bootstrap/appium-main-runner.ts +172 -0
- package/lib/{config-file.ts → bootstrap/config-file.ts} +29 -63
- package/lib/{grid-register.ts → bootstrap/grid-v3-register.ts} +35 -35
- package/lib/bootstrap/init-types.ts +31 -0
- package/lib/bootstrap/main-helpers.ts +223 -0
- package/lib/bootstrap/node-helpers.ts +180 -0
- package/lib/bootstrap/startup-config.ts +143 -0
- package/lib/cli/args.ts +10 -10
- package/lib/cli/extension-command.ts +132 -132
- package/lib/cli/extension.ts +7 -7
- package/lib/cli/parser.ts +50 -50
- package/lib/cli/setup-command.ts +2 -2
- package/lib/cli/utils.ts +33 -33
- package/lib/doctor/doctor.ts +8 -8
- package/lib/extension/driver-config.ts +165 -0
- package/lib/extension/{extension-config.js → extension-config.ts} +291 -405
- package/lib/extension/index.ts +143 -0
- package/lib/extension/manifest-migrations.ts +57 -0
- package/lib/extension/manifest.ts +369 -0
- package/lib/extension/{package-changed.js → package-changed.ts} +9 -18
- package/lib/extension/plugin-config.ts +62 -0
- package/lib/helpers/build.ts +111 -0
- package/lib/helpers/capability.ts +171 -0
- package/lib/helpers/network.ts +30 -0
- package/lib/insecure-features.ts +1 -1
- package/lib/inspector-commands.ts +6 -1
- package/lib/{logger.js → logger.ts} +1 -2
- package/lib/main.ts +60 -0
- package/lib/schema/cli-args-guards.ts +67 -0
- package/lib/schema/cli-args.ts +1 -1
- package/lib/schema/format-errors.ts +43 -0
- package/lib/schema/index.ts +2 -0
- package/lib/schema/schema.ts +51 -52
- package/lib/utils.ts +0 -331
- package/package.json +12 -13
- package/scripts/autoinstall-extensions.js +3 -0
- package/build/lib/config-file.d.ts +0 -57
- package/build/lib/config-file.d.ts.map +0 -1
- package/build/lib/config-file.js.map +0 -1
- package/build/lib/config.d.ts +0 -68
- package/build/lib/config.d.ts.map +0 -1
- package/build/lib/config.js +0 -358
- package/build/lib/config.js.map +0 -1
- package/build/lib/grid-register.d.ts +0 -35
- package/build/lib/grid-register.d.ts.map +0 -1
- package/build/lib/grid-register.js.map +0 -1
- package/lib/config.ts +0 -377
- package/lib/extension/driver-config.js +0 -245
- package/lib/extension/index.js +0 -169
- package/lib/extension/manifest-migrations.js +0 -136
- package/lib/extension/manifest.js +0 -550
- package/lib/extension/plugin-config.js +0 -112
- package/lib/main.js +0 -545
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Module containing {@link Manifest} which handles reading & writing of extension config files.
|
|
4
|
-
*/
|
|
5
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
3
|
if (k2 === undefined) k2 = k;
|
|
7
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -49,67 +46,13 @@ const constants_1 = require("../constants");
|
|
|
49
46
|
const extension_config_1 = require("./extension-config");
|
|
50
47
|
const package_changed_1 = require("./package-changed");
|
|
51
48
|
const manifest_migrations_1 = require("./manifest-migrations");
|
|
52
|
-
/**
|
|
53
|
-
* The name of the prop (`drivers`) used in `extensions.yaml` for drivers.
|
|
54
|
-
* @type {`${typeof DRIVER_TYPE}s`}
|
|
55
|
-
*/
|
|
56
49
|
const CONFIG_DATA_DRIVER_KEY = `${constants_1.DRIVER_TYPE}s`;
|
|
57
|
-
/**
|
|
58
|
-
* The name of the prop (`plugins`) used in `extensions.yaml` for plugins.
|
|
59
|
-
* @type {`${typeof PLUGIN_TYPE}s`}
|
|
60
|
-
*/
|
|
61
50
|
const CONFIG_DATA_PLUGIN_KEY = `${constants_1.PLUGIN_TYPE}s`;
|
|
62
|
-
/**
|
|
63
|
-
* @type {Readonly<ManifestData>}
|
|
64
|
-
*/
|
|
65
51
|
const INITIAL_MANIFEST_DATA = Object.freeze({
|
|
66
52
|
[CONFIG_DATA_DRIVER_KEY]: Object.freeze({}),
|
|
67
53
|
[CONFIG_DATA_PLUGIN_KEY]: Object.freeze({}),
|
|
68
54
|
schemaRev: constants_1.CURRENT_SCHEMA_REV,
|
|
69
55
|
});
|
|
70
|
-
/**
|
|
71
|
-
* Given a `package.json` return `true` if it represents an Appium Extension (either a driver or plugin).
|
|
72
|
-
*
|
|
73
|
-
* _This is a type guard; not a validator._
|
|
74
|
-
*
|
|
75
|
-
* The `package.json` must have an `appium` property which is an object.
|
|
76
|
-
* @param {any} value
|
|
77
|
-
* @returns {value is ExtPackageJson<ExtensionType>}
|
|
78
|
-
*/
|
|
79
|
-
function isExtension(value) {
|
|
80
|
-
return (lodash_1.default.isPlainObject(value) &&
|
|
81
|
-
lodash_1.default.isPlainObject(value.appium) &&
|
|
82
|
-
lodash_1.default.isString(value.name) &&
|
|
83
|
-
lodash_1.default.isString(value.version));
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Given a `package.json`, return `true` if it represents an Appium Driver.
|
|
87
|
-
*
|
|
88
|
-
* _This is a type guard; not a validator._
|
|
89
|
-
*
|
|
90
|
-
* To be considered a driver, a `package.json` must have an `appium.driverName` field.
|
|
91
|
-
*
|
|
92
|
-
* Further validation of the `appium` property happens elsewhere.
|
|
93
|
-
* @param {any} value - Value to test
|
|
94
|
-
* @returns {value is ExtPackageJson<DriverType>}
|
|
95
|
-
*/
|
|
96
|
-
function isDriver(value) {
|
|
97
|
-
return isExtension(value) && 'driverName' in value.appium && lodash_1.default.isString(value.appium.driverName);
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Given a `package.json`, return `true` if it represents an Appium Plugin.
|
|
101
|
-
*
|
|
102
|
-
* _This is a type guard; not a validator._
|
|
103
|
-
*
|
|
104
|
-
* To be considered a plugin, a `package.json` must have an `appium.pluginName` field.
|
|
105
|
-
*
|
|
106
|
-
* Further validation of the `appium` property happens elsewhere.
|
|
107
|
-
* @param {any} value - Value to test
|
|
108
|
-
* @returns {value is ExtPackageJson<PluginType>}
|
|
109
|
-
*/
|
|
110
|
-
function isPlugin(value) {
|
|
111
|
-
return isExtension(value) && 'pluginName' in value.appium && lodash_1.default.isString(value.appium.pluginName);
|
|
112
|
-
}
|
|
113
56
|
/**
|
|
114
57
|
* Handles reading & writing of extension config files.
|
|
115
58
|
*
|
|
@@ -117,81 +60,151 @@ function isPlugin(value) {
|
|
|
117
60
|
*/
|
|
118
61
|
class Manifest {
|
|
119
62
|
/**
|
|
120
|
-
*
|
|
63
|
+
* Returns the memoized manifest for an `APPIUM_HOME` directory (one instance per home).
|
|
121
64
|
*
|
|
122
|
-
*
|
|
123
|
-
* @type {ManifestData}
|
|
65
|
+
* @param appiumHome - `APPIUM_HOME` path used as the cache key
|
|
124
66
|
*/
|
|
67
|
+
static getInstance = lodash_1.default.memoize((appiumHome) => new Manifest(appiumHome));
|
|
125
68
|
#data;
|
|
126
|
-
/**
|
|
127
|
-
* Path to `APPIUM_HOME`.
|
|
128
|
-
* @type {Readonly<string>}
|
|
129
|
-
*/
|
|
130
69
|
#appiumHome;
|
|
70
|
+
#manifestPath = undefined;
|
|
71
|
+
#writing;
|
|
72
|
+
#reading;
|
|
73
|
+
constructor(appiumHome) {
|
|
74
|
+
this.#appiumHome = appiumHome;
|
|
75
|
+
this.#data = lodash_1.default.cloneDeep(INITIAL_MANIFEST_DATA);
|
|
76
|
+
}
|
|
77
|
+
/** `APPIUM_HOME` directory this manifest is tied to. */
|
|
78
|
+
get appiumHome() {
|
|
79
|
+
return this.#appiumHome;
|
|
80
|
+
}
|
|
131
81
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* Not set until {@link Manifest.read} is called.
|
|
82
|
+
* Absolute path to the extension manifest file after {@link Manifest.read} or {@link Manifest.write} has resolved it.
|
|
83
|
+
* Before that, this is `undefined`.
|
|
135
84
|
*/
|
|
136
|
-
|
|
85
|
+
get manifestPath() {
|
|
86
|
+
return this.#manifestPath;
|
|
87
|
+
}
|
|
88
|
+
/** Schema revision of the in-memory manifest data (from YAML `schemaRev`). */
|
|
89
|
+
get schemaRev() {
|
|
90
|
+
return this.#data.schemaRev;
|
|
91
|
+
}
|
|
137
92
|
/**
|
|
138
|
-
*
|
|
93
|
+
* Returns the live installed-extension map for drivers or plugins (same object as stored in memory).
|
|
94
|
+
* Mutations affect the manifest until replaced by a new object (e.g. via `read()`); `setExtension` / `deleteExtension` update this record.
|
|
139
95
|
*
|
|
140
|
-
*
|
|
141
|
-
* set to a `Promise`. When the call to `write()` is complete, the `Promise`
|
|
142
|
-
* will resolve and then this value will be set to `undefined`. Concurrent calls
|
|
143
|
-
* made while this value is a `Promise` will return the `Promise` itself.
|
|
144
|
-
* @type {Promise<boolean>|undefined}
|
|
96
|
+
* @param extType - `"driver"` or `"plugin"`
|
|
145
97
|
*/
|
|
146
|
-
|
|
98
|
+
getExtensionData(extType) {
|
|
99
|
+
const record = extType === constants_1.DRIVER_TYPE ? this.#data.drivers : this.#data.plugins;
|
|
100
|
+
return record;
|
|
101
|
+
}
|
|
147
102
|
/**
|
|
148
|
-
*
|
|
103
|
+
* Whether a driver with the given manifest key is present.
|
|
149
104
|
*
|
|
150
|
-
*
|
|
151
|
-
* set to a `Promise`. When the call to `read()` is complete, the `Promise`
|
|
152
|
-
* will resolve and then this value will be set to `undefined`. Concurrent calls
|
|
153
|
-
* made while this value is a `Promise` will return the `Promise` itself.
|
|
154
|
-
* @type {Promise<void>|undefined}
|
|
105
|
+
* @param name - Driver name as stored under `drivers` in the manifest
|
|
155
106
|
*/
|
|
156
|
-
|
|
107
|
+
hasDriver(name) {
|
|
108
|
+
return Boolean(this.#data.drivers[name]);
|
|
109
|
+
}
|
|
157
110
|
/**
|
|
158
|
-
*
|
|
111
|
+
* Whether a plugin with the given manifest key is present.
|
|
159
112
|
*
|
|
160
|
-
*
|
|
161
|
-
* @param {string} appiumHome
|
|
162
|
-
* @private
|
|
113
|
+
* @param name - Plugin name as stored under `plugins` in the manifest
|
|
163
114
|
*/
|
|
164
|
-
|
|
165
|
-
this.#
|
|
166
|
-
this.#data = lodash_1.default.cloneDeep(INITIAL_MANIFEST_DATA);
|
|
115
|
+
hasPlugin(name) {
|
|
116
|
+
return Boolean(this.#data.plugins[name]);
|
|
167
117
|
}
|
|
168
118
|
/**
|
|
169
|
-
*
|
|
119
|
+
* Loads manifest YAML from disk into memory, runs migration when needed, may sync with installed packages, and writes back if required.
|
|
120
|
+
* Concurrent calls while a read is in flight share the same in-flight work.
|
|
170
121
|
*
|
|
171
|
-
*
|
|
122
|
+
* @returns The parsed in-memory manifest data
|
|
172
123
|
*/
|
|
173
|
-
|
|
124
|
+
async read() {
|
|
125
|
+
if (this.#reading) {
|
|
126
|
+
await this.#reading;
|
|
127
|
+
return this.#data;
|
|
128
|
+
}
|
|
129
|
+
this.#reading = (async () => {
|
|
130
|
+
let data;
|
|
131
|
+
let shouldWrite = false;
|
|
132
|
+
const manifestPathResolved = await this.#setManifestPath();
|
|
133
|
+
try {
|
|
134
|
+
const yaml = await support_1.fs.readFile(manifestPathResolved, 'utf8');
|
|
135
|
+
data = YAML.parse(yaml);
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
if (err.code === 'ENOENT') {
|
|
139
|
+
data = lodash_1.default.cloneDeep(INITIAL_MANIFEST_DATA);
|
|
140
|
+
shouldWrite = true;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
throw new Error(`Appium had trouble loading the extension installation ` +
|
|
144
|
+
`cache file (${manifestPathResolved}). It may be invalid YAML. Specific error: ${err.message}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
this.#data = data;
|
|
148
|
+
if (!shouldWrite && (data.schemaRev ?? 0) < constants_1.CURRENT_SCHEMA_REV) {
|
|
149
|
+
shouldWrite = await (0, manifest_migrations_1.migrate)(this);
|
|
150
|
+
}
|
|
151
|
+
const hasAppiumDependency = await support_1.env.hasAppiumDependency(this.appiumHome);
|
|
152
|
+
if (shouldWrite || (hasAppiumDependency && (await (0, package_changed_1.packageDidChange)(this.appiumHome)))) {
|
|
153
|
+
shouldWrite = (await this.syncWithInstalledExtensions(hasAppiumDependency)) || shouldWrite;
|
|
154
|
+
}
|
|
155
|
+
if (shouldWrite) {
|
|
156
|
+
await this.write();
|
|
157
|
+
}
|
|
158
|
+
})();
|
|
159
|
+
try {
|
|
160
|
+
await this.#reading;
|
|
161
|
+
return this.#data;
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
this.#reading = undefined;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
174
167
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
168
|
+
* Serializes the current in-memory manifest to the resolved manifest path.
|
|
169
|
+
* Concurrent calls while a write is in flight share the same in-flight work.
|
|
170
|
+
*
|
|
171
|
+
* @returns `true` when the file was written successfully
|
|
177
172
|
*/
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
173
|
+
async write() {
|
|
174
|
+
if (this.#writing) {
|
|
175
|
+
return this.#writing;
|
|
176
|
+
}
|
|
177
|
+
this.#writing = (async () => {
|
|
178
|
+
const manifestPathResolved = await this.#setManifestPath();
|
|
179
|
+
try {
|
|
180
|
+
await support_1.fs.mkdirp(node_path_1.default.dirname(manifestPathResolved));
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
throw new Error(`Appium could not create the directory for the manifest file: ${node_path_1.default.dirname(manifestPathResolved)}. Original error: ${err.message}`);
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
await support_1.fs.writeFile(manifestPathResolved, YAML.stringify(this.#data), 'utf8');
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
throw new Error(`Appium could not write to manifest at ${manifestPathResolved} using APPIUM_HOME ${this.#appiumHome}. Please ensure it is writable. Original error: ${err.message}`);
|
|
191
|
+
}
|
|
192
|
+
})();
|
|
193
|
+
try {
|
|
194
|
+
return await this.#writing;
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
this.#writing = undefined;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
181
200
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
* @
|
|
201
|
+
* Scans `APPIUM_HOME` (root and `node_modules`) for Appium extension packages and merges them into the manifest.
|
|
202
|
+
*
|
|
203
|
+
* @param hasAppiumDependency - When true and the root `package.json` depends on Appium, matching extensions use the `"dev"` install type
|
|
204
|
+
* @returns `true` if any extension entries changed, `false` otherwise
|
|
185
205
|
*/
|
|
186
206
|
async syncWithInstalledExtensions(hasAppiumDependency = false) {
|
|
187
|
-
// this could be parallelized, but we can't use fs.walk as an async iterator
|
|
188
207
|
let didChange = false;
|
|
189
|
-
/**
|
|
190
|
-
* Listener for the `match` event of a `glob` instance
|
|
191
|
-
* @param {string} filepath - Path to a `package.json`
|
|
192
|
-
* @param {boolean} [devType] - If `true`, this is an extension in "dev mode"
|
|
193
|
-
* @returns {Promise<void>}
|
|
194
|
-
*/
|
|
195
208
|
const onMatch = async (filepath, devType = false) => {
|
|
196
209
|
try {
|
|
197
210
|
const pkg = JSON.parse(await support_1.fs.readFile(filepath, 'utf8'));
|
|
@@ -201,18 +214,13 @@ class Manifest {
|
|
|
201
214
|
didChange = didChange || changed;
|
|
202
215
|
}
|
|
203
216
|
}
|
|
204
|
-
catch {
|
|
217
|
+
catch {
|
|
218
|
+
// ignore invalid package.json
|
|
219
|
+
}
|
|
205
220
|
};
|
|
206
|
-
/**
|
|
207
|
-
* A list of `Promise`s which read `package.json` files looking for Appium extensions.
|
|
208
|
-
* @type {Promise<void>[]}
|
|
209
|
-
*/
|
|
210
221
|
const queue = [
|
|
211
|
-
// look at `package.json` in `APPIUM_HOME` only.
|
|
212
|
-
// this causes extensions in "dev mode" to be automatically found
|
|
213
222
|
onMatch(node_path_1.default.join(this.#appiumHome, 'package.json'), true),
|
|
214
223
|
];
|
|
215
|
-
// add dependencies to the queue
|
|
216
224
|
const filepaths = await support_1.fs.glob('node_modules/{*,@*/*}/package.json', {
|
|
217
225
|
cwd: this.#appiumHome,
|
|
218
226
|
absolute: true,
|
|
@@ -220,303 +228,120 @@ class Manifest {
|
|
|
220
228
|
for (const filepath of filepaths) {
|
|
221
229
|
queue.push(onMatch(filepath));
|
|
222
230
|
}
|
|
223
|
-
// wait for everything to finish
|
|
224
231
|
await bluebird_1.default.all(queue);
|
|
225
232
|
return didChange;
|
|
226
233
|
}
|
|
227
234
|
/**
|
|
228
|
-
*
|
|
229
|
-
* @param {string} name - Driver name
|
|
230
|
-
* @returns {boolean}
|
|
231
|
-
*/
|
|
232
|
-
hasDriver(name) {
|
|
233
|
-
return Boolean(this.#data.drivers[name]);
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Returns `true` if plugin with name `name` is registered.
|
|
237
|
-
* @param {string} name - Plugin name
|
|
238
|
-
* @returns {boolean}
|
|
239
|
-
*/
|
|
240
|
-
hasPlugin(name) {
|
|
241
|
-
return Boolean(this.#data.plugins[name]);
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Given a path to a `package.json`, add it as either a driver or plugin to the manifest.
|
|
235
|
+
* Builds manifest metadata from a `package.json` and registers it if it is a driver or plugin and the entry changed.
|
|
245
236
|
*
|
|
246
|
-
* @
|
|
247
|
-
* @param
|
|
248
|
-
* @param
|
|
249
|
-
* @
|
|
250
|
-
* @
|
|
237
|
+
* @param pkgJson - Parsed extension `package.json`
|
|
238
|
+
* @param pkgPath - Path to that `package.json` (install path is derived from its directory)
|
|
239
|
+
* @param installType - How the package was discovered (`npm` vs `dev`)
|
|
240
|
+
* @returns `true` if the manifest was updated, `false` if unchanged or already matched
|
|
241
|
+
* @throws TypeError if the package is not a valid driver or plugin extension
|
|
251
242
|
*/
|
|
252
243
|
addExtensionFromPackage(pkgJson, pkgPath, installType = extension_config_1.INSTALL_TYPE_NPM) {
|
|
253
244
|
const extensionPath = node_path_1.default.dirname(pkgPath);
|
|
254
|
-
/**
|
|
255
|
-
* @type {InternalMetadata}
|
|
256
|
-
*/
|
|
257
245
|
const internal = {
|
|
258
|
-
pkgName:
|
|
259
|
-
version:
|
|
246
|
+
pkgName: pkgJson.name,
|
|
247
|
+
version: pkgJson.version,
|
|
260
248
|
appiumVersion: pkgJson.peerDependencies?.appium,
|
|
261
249
|
installType,
|
|
262
250
|
installSpec: `${pkgJson.name}@${pkgJson.version}`,
|
|
263
251
|
installPath: extensionPath,
|
|
264
252
|
};
|
|
265
253
|
if (isDriver(pkgJson)) {
|
|
254
|
+
const driverName = pkgJson.appium.driverName;
|
|
266
255
|
const value = {
|
|
267
256
|
...lodash_1.default.omit(pkgJson.appium, 'driverName'),
|
|
268
257
|
...internal,
|
|
269
258
|
};
|
|
270
|
-
if (!lodash_1.default.isEqual(value, this.#data.drivers[
|
|
271
|
-
this.setExtension(
|
|
272
|
-
/** @type {ExtType} */ (constants_1.DRIVER_TYPE), pkgJson.appium.driverName,
|
|
273
|
-
/** @type {ExtManifest<ExtType>} */ (value));
|
|
259
|
+
if (!lodash_1.default.isEqual(value, this.#data.drivers[driverName])) {
|
|
260
|
+
this.setExtension(constants_1.DRIVER_TYPE, driverName, value);
|
|
274
261
|
return true;
|
|
275
262
|
}
|
|
276
263
|
return false;
|
|
277
264
|
}
|
|
278
|
-
|
|
265
|
+
if (isPlugin(pkgJson)) {
|
|
266
|
+
const pluginName = pkgJson.appium.pluginName;
|
|
279
267
|
const value = {
|
|
280
268
|
...lodash_1.default.omit(pkgJson.appium, 'pluginName'),
|
|
281
269
|
...internal,
|
|
282
270
|
};
|
|
283
|
-
if (!lodash_1.default.isEqual(value, this.#data.plugins[
|
|
284
|
-
this.setExtension(
|
|
285
|
-
/** @type {ExtType} */ (constants_1.PLUGIN_TYPE), pkgJson.appium.pluginName,
|
|
286
|
-
/** @type {ExtManifest<ExtType>} */ (value));
|
|
271
|
+
if (!lodash_1.default.isEqual(value, this.#data.plugins[pluginName])) {
|
|
272
|
+
this.setExtension(constants_1.PLUGIN_TYPE, pluginName, value);
|
|
287
273
|
return true;
|
|
288
274
|
}
|
|
289
275
|
return false;
|
|
290
276
|
}
|
|
291
|
-
|
|
292
|
-
throw new TypeError(`The extension in ${extensionPath} is neither a valid ${constants_1.DRIVER_TYPE} nor a valid ${constants_1.PLUGIN_TYPE}.`);
|
|
293
|
-
}
|
|
277
|
+
throw new TypeError(`The extension in ${extensionPath} is neither a valid ${constants_1.DRIVER_TYPE} nor a valid ${constants_1.PLUGIN_TYPE}.`);
|
|
294
278
|
}
|
|
295
279
|
/**
|
|
296
|
-
*
|
|
297
|
-
* `extData`, `extType`, and `extName` have already been determined.
|
|
280
|
+
* Stores a deep-cloned copy of extension metadata under the given type and name.
|
|
298
281
|
*
|
|
299
|
-
*
|
|
300
|
-
* @
|
|
301
|
-
* @param
|
|
302
|
-
* @
|
|
303
|
-
* @param {ExtManifest<ExtType>} extData - Extension metadata
|
|
304
|
-
* @returns {ExtManifest<ExtType>} A clone of `extData`, potentially with a mutated `appiumVersion` field
|
|
282
|
+
* @param extType - `"driver"` or `"plugin"`
|
|
283
|
+
* @param extName - Manifest key for the extension
|
|
284
|
+
* @param extData - Full extension entry to persist in memory
|
|
285
|
+
* @returns The cloned data now held in the manifest
|
|
305
286
|
*/
|
|
306
287
|
setExtension(extType, extName, extData) {
|
|
307
288
|
const data = lodash_1.default.cloneDeep(extData);
|
|
308
|
-
|
|
289
|
+
if (extType === constants_1.DRIVER_TYPE) {
|
|
290
|
+
this.#data.drivers[extName] = data;
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
this.#data.plugins[extName] = data;
|
|
294
|
+
}
|
|
309
295
|
return data;
|
|
310
296
|
}
|
|
311
297
|
/**
|
|
312
|
-
*
|
|
313
|
-
*
|
|
298
|
+
* Updates the in-memory manifest schema revision (typically during migration).
|
|
299
|
+
*
|
|
300
|
+
* @param rev - New `schemaRev` value
|
|
314
301
|
*/
|
|
315
302
|
setSchemaRev(rev) {
|
|
316
303
|
this.#data.schemaRev = rev;
|
|
317
304
|
}
|
|
318
305
|
/**
|
|
319
|
-
*
|
|
320
|
-
* @param {ExtensionType} extType
|
|
321
|
-
* @param {string} extName
|
|
322
|
-
*/
|
|
323
|
-
deleteExtension(extType, extName) {
|
|
324
|
-
delete this.#data[`${extType}s`][extName];
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Returns the `APPIUM_HOME` path
|
|
328
|
-
*/
|
|
329
|
-
get appiumHome() {
|
|
330
|
-
return this.#appiumHome;
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Returns the path to the manifest file (`extensions.yaml`)
|
|
334
|
-
*/
|
|
335
|
-
get manifestPath() {
|
|
336
|
-
return this.#manifestPath;
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Returns the schema rev of this manifest
|
|
340
|
-
*/
|
|
341
|
-
get schemaRev() {
|
|
342
|
-
return this.#data.schemaRev;
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Returns extension data for a particular type.
|
|
346
|
-
*
|
|
347
|
-
* @template {ExtensionType} ExtType
|
|
348
|
-
* @param {ExtType} extType
|
|
349
|
-
* @returns {Readonly<ExtRecord<ExtType>>}
|
|
350
|
-
*/
|
|
351
|
-
getExtensionData(extType) {
|
|
352
|
-
return this.#data[ /** @type {string} */(`${extType}s`)];
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Reads manifest from disk and _overwrites_ the internal data.
|
|
356
|
-
*
|
|
357
|
-
* If the manifest does not exist on disk, an
|
|
358
|
-
* {@link INITIAL_MANIFEST_DATA "empty"} manifest file will be created, as
|
|
359
|
-
* well as its directory if needed.
|
|
360
|
-
*
|
|
361
|
-
* This will also, if necessary:
|
|
362
|
-
* 1. perform a migration of the manifest data
|
|
363
|
-
* 2. sync the manifest with extensions on-disk (kind of like "auto
|
|
364
|
-
* discovery")
|
|
365
|
-
* 3. write the manifest to disk.
|
|
306
|
+
* Removes an extension entry from the manifest data in memory (does not write to disk by itself).
|
|
366
307
|
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
* @returns {Promise<ManifestData>} The data
|
|
308
|
+
* @param extType - `"driver"` or `"plugin"`
|
|
309
|
+
* @param extName - Manifest key to remove
|
|
370
310
|
*/
|
|
371
|
-
|
|
372
|
-
if (
|
|
373
|
-
|
|
374
|
-
return this.#data;
|
|
375
|
-
}
|
|
376
|
-
this.#reading = (async () => {
|
|
377
|
-
/** @type {ManifestData} */
|
|
378
|
-
let data;
|
|
379
|
-
/**
|
|
380
|
-
* This will be `true` if, after reading, we need to update the manifest data
|
|
381
|
-
* and write it again to disk.
|
|
382
|
-
*/
|
|
383
|
-
let shouldWrite = false;
|
|
384
|
-
await this.#setManifestPath();
|
|
385
|
-
try {
|
|
386
|
-
const yaml = await support_1.fs.readFile(this.#manifestPath, 'utf8');
|
|
387
|
-
data = YAML.parse(yaml);
|
|
388
|
-
}
|
|
389
|
-
catch (err) {
|
|
390
|
-
if (err.code === 'ENOENT') {
|
|
391
|
-
data = lodash_1.default.cloneDeep(INITIAL_MANIFEST_DATA);
|
|
392
|
-
shouldWrite = true;
|
|
393
|
-
}
|
|
394
|
-
else if (this.#manifestPath) {
|
|
395
|
-
throw new Error(`Appium had trouble loading the extension installation ` +
|
|
396
|
-
`cache file (${this.#manifestPath}). It may be invalid YAML. Specific error: ${err.message}`);
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
throw new Error(`Appium encountered an unknown problem. Specific error: ${err.message}`);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
this.#data = data;
|
|
403
|
-
/**
|
|
404
|
-
* the only way `shouldWrite` is `true` is if we have a new file. a new
|
|
405
|
-
* file will get the latest schema revision, so we can skip the migration.
|
|
406
|
-
*/
|
|
407
|
-
if (!shouldWrite && (data.schemaRev ?? 0) < constants_1.CURRENT_SCHEMA_REV) {
|
|
408
|
-
shouldWrite = await (0, manifest_migrations_1.migrate)(this);
|
|
409
|
-
}
|
|
410
|
-
const hasAppiumDependency = await support_1.env.hasAppiumDependency(this.appiumHome);
|
|
411
|
-
/**
|
|
412
|
-
* we still may want to sync with installed extensions even if we have a
|
|
413
|
-
* new file. right now this is limited to the following cases:
|
|
414
|
-
* 1. we have a brand new manifest file
|
|
415
|
-
* 2. we have performed a migration on a manifest file
|
|
416
|
-
* 3. `appium` is a dependency within `package.json`, and `package.json`
|
|
417
|
-
* has changed since last time we checked.
|
|
418
|
-
*
|
|
419
|
-
* It may also make sense to sync with the extensions in an arbitrary
|
|
420
|
-
* `APPIUM_HOME`, but we don't do that here.
|
|
421
|
-
*/
|
|
422
|
-
if (shouldWrite || (hasAppiumDependency && (await (0, package_changed_1.packageDidChange)(this.appiumHome)))) {
|
|
423
|
-
shouldWrite = (await this.syncWithInstalledExtensions(hasAppiumDependency)) || shouldWrite;
|
|
424
|
-
}
|
|
425
|
-
if (shouldWrite) {
|
|
426
|
-
await this.write();
|
|
427
|
-
}
|
|
428
|
-
})();
|
|
429
|
-
try {
|
|
430
|
-
await this.#reading;
|
|
431
|
-
return this.#data;
|
|
311
|
+
deleteExtension(extType, extName) {
|
|
312
|
+
if (extType === constants_1.DRIVER_TYPE) {
|
|
313
|
+
delete this.#data.drivers[extName];
|
|
432
314
|
}
|
|
433
|
-
|
|
434
|
-
this.#
|
|
315
|
+
else {
|
|
316
|
+
delete this.#data.plugins[extName];
|
|
435
317
|
}
|
|
436
318
|
}
|
|
437
|
-
/**
|
|
438
|
-
* Ensures the internal manifest path is set.
|
|
439
|
-
*
|
|
440
|
-
* Creates the directory if necessary.
|
|
441
|
-
* @returns {Promise<string>}
|
|
442
|
-
*/
|
|
443
319
|
async #setManifestPath() {
|
|
444
320
|
if (!this.#manifestPath) {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
if (node_path_1.default.relative(this.#appiumHome,
|
|
448
|
-
throw new Error(`Mismatch between location of APPIUM_HOME and manifest file. APPIUM_HOME: ${this.appiumHome}, manifest file: ${
|
|
321
|
+
const resolved = await support_1.env.resolveManifestPath(this.#appiumHome);
|
|
322
|
+
this.#manifestPath = resolved;
|
|
323
|
+
if (node_path_1.default.relative(this.#appiumHome, resolved).startsWith('.')) {
|
|
324
|
+
throw new Error(`Mismatch between location of APPIUM_HOME and manifest file. APPIUM_HOME: ${this.appiumHome}, manifest file: ${resolved}`);
|
|
449
325
|
}
|
|
450
326
|
}
|
|
451
327
|
return this.#manifestPath;
|
|
452
328
|
}
|
|
453
|
-
/**
|
|
454
|
-
* Writes the data if it need s writing.
|
|
455
|
-
*
|
|
456
|
-
* If the `schemaRev` prop needs updating, the file will be written.
|
|
457
|
-
*
|
|
458
|
-
* @todo If this becomes too much of a bottleneck, throttle it.
|
|
459
|
-
* @returns {Promise<boolean>} Whether the data was written
|
|
460
|
-
*/
|
|
461
|
-
async write() {
|
|
462
|
-
if (this.#writing) {
|
|
463
|
-
return this.#writing;
|
|
464
|
-
}
|
|
465
|
-
this.#writing = (async () => {
|
|
466
|
-
await this.#setManifestPath();
|
|
467
|
-
try {
|
|
468
|
-
await support_1.fs.mkdirp(node_path_1.default.dirname(this.#manifestPath));
|
|
469
|
-
}
|
|
470
|
-
catch (err) {
|
|
471
|
-
throw new Error(`Appium could not create the directory for the manifest file: ${node_path_1.default.dirname(this.#manifestPath)}. Original error: ${err.message}`);
|
|
472
|
-
}
|
|
473
|
-
try {
|
|
474
|
-
await support_1.fs.writeFile(this.#manifestPath, YAML.stringify(this.#data), 'utf8');
|
|
475
|
-
return true;
|
|
476
|
-
}
|
|
477
|
-
catch (err) {
|
|
478
|
-
throw new Error(`Appium could not write to manifest at ${this.#manifestPath} using APPIUM_HOME ${this.#appiumHome}. Please ensure it is writable. Original error: ${err.message}`);
|
|
479
|
-
}
|
|
480
|
-
})();
|
|
481
|
-
try {
|
|
482
|
-
return await this.#writing;
|
|
483
|
-
}
|
|
484
|
-
finally {
|
|
485
|
-
this.#writing = undefined;
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
329
|
}
|
|
489
330
|
exports.Manifest = Manifest;
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
* @template {ExtensionType} ExtType
|
|
508
|
-
* @typedef {import('appium/types').ExtPackageJson<ExtType>} ExtPackageJson
|
|
509
|
-
*/
|
|
510
|
-
/**
|
|
511
|
-
* @template {ExtensionType} ExtType
|
|
512
|
-
* @typedef {import('appium/types').ExtManifest<ExtType>} ExtManifest
|
|
513
|
-
*/
|
|
514
|
-
/**
|
|
515
|
-
* @template {ExtensionType} ExtType
|
|
516
|
-
* @typedef {import('appium/types').ExtRecord<ExtType>} ExtRecord
|
|
517
|
-
*/
|
|
518
|
-
/**
|
|
519
|
-
* Either `driver` or `plugin` rn
|
|
520
|
-
* @typedef {import('@appium/types').ExtensionType} ExtensionType
|
|
521
|
-
*/
|
|
331
|
+
function isExtension(value) {
|
|
332
|
+
return (lodash_1.default.isPlainObject(value) &&
|
|
333
|
+
lodash_1.default.isPlainObject(value.appium) &&
|
|
334
|
+
lodash_1.default.isString(value.name) &&
|
|
335
|
+
lodash_1.default.isString(value.version));
|
|
336
|
+
}
|
|
337
|
+
function isDriver(value) {
|
|
338
|
+
return (isExtension(value) &&
|
|
339
|
+
'driverName' in value.appium &&
|
|
340
|
+
lodash_1.default.isString(value.appium.driverName));
|
|
341
|
+
}
|
|
342
|
+
function isPlugin(value) {
|
|
343
|
+
return (isExtension(value) &&
|
|
344
|
+
'pluginName' in value.appium &&
|
|
345
|
+
lodash_1.default.isString(value.appium.pluginName));
|
|
346
|
+
}
|
|
522
347
|
//# sourceMappingURL=manifest.js.map
|