1 | #!/usr/bin/env node
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | const B = require('bluebird');
|
25 | const path = require('node:path');
|
26 | const {realpath} = require('node:fs/promises');
|
27 |
|
28 | B.config({
|
29 | cancellation: true,
|
30 | });
|
31 |
|
32 |
|
33 | let runExtensionCommand;
|
34 |
|
35 | let DRIVER_TYPE;
|
36 |
|
37 | let PLUGIN_TYPE;
|
38 |
|
39 | let loadExtensions;
|
40 |
|
41 | const _ = require('lodash');
|
42 | const wrap = _.partial(
|
43 | require('wrap-ansi'),
|
44 | _,
|
45 | process.stderr.columns ?? process.stdout.columns ?? 80
|
46 | );
|
47 | const ora = require('ora');
|
48 |
|
49 |
|
50 | let env;
|
51 |
|
52 | let util;
|
53 |
|
54 | let logger;
|
55 |
|
56 | function log(message) {
|
57 | console.error(wrap(`[Appium] ${message}`));
|
58 | }
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 | async function isDevEnvironment() {
|
70 | return (
|
71 | process.env.npm_config_local_prefix &&
|
72 | path.join(process.env.npm_config_local_prefix, 'packages', 'appium') ===
|
73 | (await realpath(path.join(__dirname, '..')))
|
74 | );
|
75 | }
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | async function init() {
|
82 | if (await isDevEnvironment()) {
|
83 | log('Dev environment likely; skipping automatic installation of extensions');
|
84 | return false;
|
85 | }
|
86 | try {
|
87 | ({env, util, logger} = require('@appium/support'));
|
88 |
|
89 | ({runExtensionCommand} = require('../build/lib/cli/extension'));
|
90 | ({DRIVER_TYPE, PLUGIN_TYPE} = require('../build/lib/constants'));
|
91 |
|
92 | ({loadExtensions} = require('../build/lib/extension'));
|
93 | logger.getLogger('Appium').level = 'error';
|
94 |
|
95 |
|
96 | if (!process.env.npm_config_global && (await env.hasAppiumDependency(process.cwd()))) {
|
97 | log(`Found local Appium installation; skipping automatic installation of extensions.`);
|
98 | return false;
|
99 | }
|
100 | return true;
|
101 | } catch {
|
102 | log('Dev environment likely; skipping automatic installation of extensions');
|
103 | return false;
|
104 | }
|
105 | }
|
106 |
|
107 | async function main() {
|
108 | if (!(await init())) {
|
109 | return;
|
110 | }
|
111 |
|
112 | const driverEnv = process.env.npm_config_drivers;
|
113 | const pluginEnv = process.env.npm_config_plugins;
|
114 |
|
115 | const spinner = ora({
|
116 | text: 'Looking for extensions to automatically install...',
|
117 | prefixText: '[Appium]',
|
118 | }).start();
|
119 |
|
120 | if (!driverEnv && !pluginEnv) {
|
121 | spinner.succeed(
|
122 | wrap(`No drivers or plugins to automatically install.
|
123 | If desired, provide arguments with comma-separated values "--drivers=<known_driver>[,known_driver...]" and/or "--plugins=<known_plugin>[,known_plugin...]" to the "npm install appium" command. The specified extensions will be installed automatically with Appium. Note: to see the list of known extensions, run "appium <driver|plugin> list".`)
|
124 | );
|
125 | return;
|
126 | }
|
127 |
|
128 | |
129 |
|
130 |
|
131 | const specs = [
|
132 | [DRIVER_TYPE, driverEnv],
|
133 | [PLUGIN_TYPE, pluginEnv],
|
134 | ];
|
135 |
|
136 | spinner.start('Resolving Appium home directory...');
|
137 | const appiumHome = await env.resolveAppiumHome();
|
138 | spinner.succeed(`Found Appium home: ${appiumHome}`);
|
139 |
|
140 | spinner.start('Loading extension data...');
|
141 | const {driverConfig, pluginConfig} = await loadExtensions(appiumHome);
|
142 | spinner.succeed('Loaded extension data.');
|
143 |
|
144 | const installedStats = {[DRIVER_TYPE]: 0, [PLUGIN_TYPE]: 0};
|
145 | for (const [type, extEnv] of specs) {
|
146 | if (extEnv) {
|
147 | for await (let ext of extEnv.split(',')) {
|
148 | ext = ext.trim();
|
149 | try {
|
150 | await checkAndInstallExtension({
|
151 | runExtensionCommand,
|
152 | appiumHome,
|
153 | type,
|
154 | ext,
|
155 | driverConfig,
|
156 | pluginConfig,
|
157 | spinner,
|
158 | });
|
159 | installedStats[type]++;
|
160 | } catch (e) {
|
161 | spinner.fail(`Could not install ${type} "${ext}": ${e.message}`);
|
162 | if (process.env.CI) {
|
163 | process.exitCode = 1;
|
164 | }
|
165 | return;
|
166 | }
|
167 | }
|
168 | }
|
169 | }
|
170 | spinner.succeed(
|
171 | `Done. ${installedStats[DRIVER_TYPE]} ${util.pluralize(
|
172 | 'driver',
|
173 | installedStats[DRIVER_TYPE]
|
174 | )} and ${installedStats[PLUGIN_TYPE]} ${util.pluralize(
|
175 | 'plugin',
|
176 | installedStats[PLUGIN_TYPE]
|
177 | )} are installed.`
|
178 | );
|
179 | }
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 | async function checkAndInstallExtension({
|
187 | runExtensionCommand,
|
188 | appiumHome,
|
189 | type,
|
190 | ext,
|
191 | driverConfig,
|
192 | pluginConfig,
|
193 | spinner,
|
194 | }) {
|
195 | const extList = await runExtensionCommand(
|
196 |
|
197 | {
|
198 | appiumHome,
|
199 | subcommand: type,
|
200 | [`${type}Command`]: 'list',
|
201 | showInstalled: true,
|
202 | suppressOutput: true,
|
203 | },
|
204 | type === DRIVER_TYPE ? driverConfig : pluginConfig
|
205 | );
|
206 | if (extList[ext]) {
|
207 | spinner.info(`The ${type} "${ext}" is already installed.`);
|
208 | return;
|
209 | }
|
210 | spinner.start(`Installing ${type} "${ext}"...`);
|
211 | await runExtensionCommand(
|
212 |
|
213 | {
|
214 | subcommand: type,
|
215 | appiumHome,
|
216 | [`${type}Command`]: 'install',
|
217 | suppressOutput: true,
|
218 | [type]: ext,
|
219 | },
|
220 | type === DRIVER_TYPE ? driverConfig : pluginConfig
|
221 | );
|
222 | spinner.succeed(`Installed ${type} "${ext}".`);
|
223 | }
|
224 |
|
225 | if (require.main === module) {
|
226 | main().catch((e) => {
|
227 | log(e);
|
228 | process.exitCode = 1;
|
229 | });
|
230 | }
|
231 |
|
232 | module.exports = main;
|
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|