appium 3.2.2 → 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} +62 -138
- 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/bootstrap/grid-v3-register.js +185 -0
- 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 +16 -12
- package/build/lib/cli/args.d.ts.map +1 -1
- package/build/lib/cli/args.js +20 -40
- package/build/lib/cli/args.js.map +1 -1
- package/build/lib/cli/driver-command.d.ts +51 -93
- package/build/lib/cli/driver-command.d.ts.map +1 -1
- package/build/lib/cli/driver-command.js +11 -66
- package/build/lib/cli/driver-command.js.map +1 -1
- package/build/lib/cli/extension-command.d.ts +173 -377
- package/build/lib/cli/extension-command.d.ts.map +1 -1
- package/build/lib/cli/extension-command.js +387 -656
- package/build/lib/cli/extension-command.js.map +1 -1
- package/build/lib/cli/extension.d.ts +10 -15
- package/build/lib/cli/extension.d.ts.map +1 -1
- package/build/lib/cli/extension.js +15 -33
- package/build/lib/cli/extension.js.map +1 -1
- package/build/lib/cli/parser.d.ts +37 -66
- package/build/lib/cli/parser.d.ts.map +1 -1
- package/build/lib/cli/parser.js +69 -104
- package/build/lib/cli/parser.js.map +1 -1
- package/build/lib/cli/plugin-command.d.ts +50 -90
- package/build/lib/cli/plugin-command.d.ts.map +1 -1
- package/build/lib/cli/plugin-command.js +11 -63
- package/build/lib/cli/plugin-command.js.map +1 -1
- package/build/lib/cli/setup-command.d.ts +21 -26
- package/build/lib/cli/setup-command.d.ts.map +1 -1
- package/build/lib/cli/setup-command.js +19 -61
- package/build/lib/cli/setup-command.js.map +1 -1
- package/build/lib/cli/utils.d.ts +33 -35
- package/build/lib/cli/utils.d.ts.map +1 -1
- package/build/lib/cli/utils.js +48 -50
- package/build/lib/cli/utils.js.map +1 -1
- package/build/lib/constants.d.ts +23 -23
- package/build/lib/constants.d.ts.map +1 -1
- package/build/lib/constants.js +10 -15
- package/build/lib/constants.js.map +1 -1
- package/build/lib/doctor/doctor.d.ts +40 -57
- package/build/lib/doctor/doctor.d.ts.map +1 -1
- package/build/lib/doctor/doctor.js +31 -62
- 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/logsink.d.ts +13 -22
- package/build/lib/logsink.d.ts.map +1 -1
- package/build/lib/logsink.js +48 -103
- package/build/lib/logsink.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/arg-spec.d.ts +32 -107
- package/build/lib/schema/arg-spec.d.ts.map +1 -1
- package/build/lib/schema/arg-spec.js +11 -107
- package/build/lib/schema/arg-spec.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.d.ts +3 -15
- package/build/lib/schema/cli-args.d.ts.map +1 -1
- package/build/lib/schema/cli-args.js +17 -107
- package/build/lib/schema/cli-args.js.map +1 -1
- package/build/lib/schema/cli-transformers.d.ts +15 -12
- package/build/lib/schema/cli-transformers.d.ts.map +1 -1
- package/build/lib/schema/cli-transformers.js +15 -45
- package/build/lib/schema/cli-transformers.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 +4 -2
- 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/keywords.d.ts +12 -20
- package/build/lib/schema/keywords.d.ts.map +1 -1
- package/build/lib/schema/keywords.js +6 -51
- package/build/lib/schema/keywords.js.map +1 -1
- package/build/lib/schema/schema.d.ts +106 -231
- package/build/lib/schema/schema.d.ts.map +1 -1
- package/build/lib/schema/schema.js +88 -358
- package/build/lib/schema/schema.js.map +1 -1
- package/build/lib/utils.d.ts +7 -267
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +10 -409
- 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/bootstrap/config-file.ts +178 -0
- package/lib/bootstrap/grid-v3-register.ts +250 -0
- 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.js → args.ts} +45 -56
- package/lib/cli/driver-command.ts +122 -0
- package/lib/cli/{extension-command.js → extension-command.ts} +827 -906
- package/lib/cli/extension.ts +65 -0
- package/lib/cli/{parser.js → parser.ts} +93 -116
- package/lib/cli/plugin-command.ts +117 -0
- package/lib/cli/{setup-command.js → setup-command.ts} +59 -74
- package/lib/cli/utils.ts +97 -0
- package/lib/{constants.js → constants.ts} +30 -41
- package/lib/doctor/{doctor.js → doctor.ts} +82 -92
- 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/{logsink.js → logsink.ts} +91 -137
- package/lib/main.ts +60 -0
- package/lib/schema/arg-spec.ts +131 -0
- package/lib/schema/cli-args-guards.ts +67 -0
- package/lib/schema/cli-args.ts +171 -0
- package/lib/schema/cli-transformers.ts +83 -0
- package/lib/schema/format-errors.ts +43 -0
- package/lib/schema/index.ts +4 -0
- package/lib/schema/keywords.ts +96 -0
- package/lib/schema/schema.ts +448 -0
- package/lib/utils.ts +73 -0
- package/package.json +17 -18
- package/scripts/autoinstall-extensions.js +3 -0
- package/build/lib/config-file.d.ts +0 -100
- 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 -70
- package/build/lib/config.d.ts.map +0 -1
- package/build/lib/config.js +0 -390
- package/build/lib/config.js.map +0 -1
- package/build/lib/grid-register.d.ts +0 -10
- package/build/lib/grid-register.d.ts.map +0 -1
- package/build/lib/grid-register.js +0 -134
- package/build/lib/grid-register.js.map +0 -1
- package/lib/cli/driver-command.js +0 -174
- package/lib/cli/extension.js +0 -74
- package/lib/cli/plugin-command.js +0 -164
- package/lib/cli/utils.js +0 -91
- package/lib/config-file.js +0 -228
- package/lib/config.js +0 -389
- 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/grid-register.js +0 -146
- package/lib/main.js +0 -545
- package/lib/schema/arg-spec.js +0 -229
- package/lib/schema/cli-args.js +0 -254
- package/lib/schema/cli-transformers.js +0 -113
- package/lib/schema/index.js +0 -2
- package/lib/schema/keywords.js +0 -136
- package/lib/schema/schema.js +0 -725
- package/lib/utils.js +0 -512
package/lib/bidi-commands.ts
CHANGED
|
@@ -5,11 +5,7 @@ import {errors} from '@appium/base-driver';
|
|
|
5
5
|
import {BIDI_BASE_PATH, BIDI_EVENT_NAME} from './constants';
|
|
6
6
|
import WebSocket from 'ws';
|
|
7
7
|
import os from 'node:os';
|
|
8
|
-
import {
|
|
9
|
-
isBroadcastIp,
|
|
10
|
-
fetchInterfaces,
|
|
11
|
-
V4_BROADCAST_IP,
|
|
12
|
-
} from './utils';
|
|
8
|
+
import {isBroadcastIp, fetchInterfaces, V4_BROADCAST_IP} from './helpers/network';
|
|
13
9
|
import type {IncomingMessage} from 'node:http';
|
|
14
10
|
import type {AppiumDriver} from './appium';
|
|
15
11
|
import type {
|
|
@@ -99,15 +95,6 @@ export function onBidiConnection(this: AppiumDriver, ws: WebSocket, req: Incomin
|
|
|
99
95
|
}
|
|
100
96
|
}
|
|
101
97
|
|
|
102
|
-
function wrapCommandWithPlugins(driver: ExtensionCore, plugins: ExtensionCore[], method: string, params: StringRecord): () => Promise<BiDiResultData> {
|
|
103
|
-
const [moduleName, methodName] = method.split('.');
|
|
104
|
-
let next = async () => await driver.executeBidiCommand(method, params);
|
|
105
|
-
for (const plugin of plugins.filter((p) => p.doesBidiCommandExist(moduleName, methodName))) {
|
|
106
|
-
next = ((_next) => async () => await plugin.executeBidiCommand(method, params, _next, driver))(next);
|
|
107
|
-
}
|
|
108
|
-
return next;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
98
|
/**
|
|
112
99
|
* @param data
|
|
113
100
|
* @param driver
|
|
@@ -204,6 +191,15 @@ export function cleanupBidiSockets(this: AppiumDriver, sessionId: string): void
|
|
|
204
191
|
delete this.bidiProxyClients[sessionId];
|
|
205
192
|
}
|
|
206
193
|
|
|
194
|
+
function wrapCommandWithPlugins(driver: ExtensionCore, plugins: ExtensionCore[], method: string, params: StringRecord): () => Promise<BiDiResultData> {
|
|
195
|
+
const [moduleName, methodName] = method.split('.');
|
|
196
|
+
let next = async () => await driver.executeBidiCommand(method, params);
|
|
197
|
+
for (const plugin of plugins.filter((p) => p.doesBidiCommandExist(moduleName, methodName))) {
|
|
198
|
+
next = ((_next) => async () => await plugin.executeBidiCommand(method, params, _next, driver))(next);
|
|
199
|
+
}
|
|
200
|
+
return next;
|
|
201
|
+
}
|
|
202
|
+
|
|
207
203
|
// #region Private functions
|
|
208
204
|
|
|
209
205
|
/**
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {init as logsinkInit} from '../logsink';
|
|
2
|
+
import {log as logger} from '../logger';
|
|
3
|
+
import {util, env} from '@appium/support';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import type {DriverOpts} from '@appium/types';
|
|
6
|
+
import {AppiumDriver, type AppiumDriverConstraints} from '../appium';
|
|
7
|
+
import {runExtensionCommand} from '../cli/extension';
|
|
8
|
+
import {runSetupCommand} from '../cli/setup-command';
|
|
9
|
+
import {getParser, ArgParser} from '../cli/parser';
|
|
10
|
+
import {readConfigFile} from './config-file';
|
|
11
|
+
import {getNonDefaultServerArgs, showConfig} from './startup-config';
|
|
12
|
+
import {adjustNodePath, requireDir, showDebugInfo} from './node-helpers';
|
|
13
|
+
import {loadExtensions, type ExtensionConfigs} from '../extension';
|
|
14
|
+
import {SERVER_SUBCOMMAND} from '../constants';
|
|
15
|
+
import {injectAppiumSymlinks} from '../cli/extension-command';
|
|
16
|
+
import {getDefaultsForSchema} from '../schema/schema';
|
|
17
|
+
import {
|
|
18
|
+
isDriverCommandArgs,
|
|
19
|
+
isExtensionCommandArgs,
|
|
20
|
+
isPluginCommandArgs,
|
|
21
|
+
isServerCommandArgs,
|
|
22
|
+
isSetupCommandArgs,
|
|
23
|
+
} from '../schema/cli-args-guards';
|
|
24
|
+
import type {
|
|
25
|
+
Args,
|
|
26
|
+
CliCommand,
|
|
27
|
+
CliCommandServer,
|
|
28
|
+
CliCommandSetupSubcommand,
|
|
29
|
+
CliExtensionSubcommand,
|
|
30
|
+
ParsedArgs,
|
|
31
|
+
} from 'appium/types';
|
|
32
|
+
import {determineAppiumHomeSource, preflightChecks} from './main-helpers';
|
|
33
|
+
import type {InitResult, PreConfigArgs} from './init-types';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Parses CLI/programmatic args, loads config and extensions, and returns server-ready state or runs extension/setup flows.
|
|
37
|
+
*/
|
|
38
|
+
export class AppiumInitializer {
|
|
39
|
+
private throwInsteadOfExit = false;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Resolves Appium home, loads config, and either returns server-ready state for the server subcommand
|
|
43
|
+
* or performs setup/extension CLI work and returns an empty result.
|
|
44
|
+
*
|
|
45
|
+
* @param args - Optional programmatic args; when omitted, parses `process.argv`
|
|
46
|
+
*/
|
|
47
|
+
async init<
|
|
48
|
+
Cmd extends CliCommand = CliCommandServer,
|
|
49
|
+
SubCmd extends CliExtensionSubcommand | CliCommandSetupSubcommand | void = void,
|
|
50
|
+
>(args?: Args<Cmd, SubCmd>): Promise<InitResult<Cmd>> {
|
|
51
|
+
this.throwInsteadOfExit = false;
|
|
52
|
+
|
|
53
|
+
const appiumHome = args?.appiumHome ?? (await env.resolveAppiumHome());
|
|
54
|
+
const appiumHomeSourceName = determineAppiumHomeSource(args?.appiumHome);
|
|
55
|
+
await requireDir(appiumHome, false, appiumHomeSourceName);
|
|
56
|
+
|
|
57
|
+
adjustNodePath();
|
|
58
|
+
|
|
59
|
+
const {driverConfig, pluginConfig} = await loadExtensions(appiumHome);
|
|
60
|
+
|
|
61
|
+
const {preConfigArgs, throwInsteadOfExit} = await this.parsePreConfigArgs(args);
|
|
62
|
+
this.throwInsteadOfExit = throwInsteadOfExit;
|
|
63
|
+
|
|
64
|
+
const configResult = await readConfigFile(preConfigArgs.configFile);
|
|
65
|
+
this.assertConfigFileOk(configResult);
|
|
66
|
+
|
|
67
|
+
if (isServerCommandArgs(preConfigArgs)) {
|
|
68
|
+
return this.finishServerInit(
|
|
69
|
+
preConfigArgs,
|
|
70
|
+
configResult,
|
|
71
|
+
driverConfig,
|
|
72
|
+
pluginConfig,
|
|
73
|
+
appiumHome,
|
|
74
|
+
appiumHomeSourceName,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (isSetupCommandArgs(preConfigArgs)) {
|
|
79
|
+
await runSetupCommand(preConfigArgs, driverConfig, pluginConfig);
|
|
80
|
+
return {} as InitResult<Cmd>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
await requireDir(appiumHome, true, appiumHomeSourceName);
|
|
84
|
+
await this.runExtensionCliIfNeeded(preConfigArgs, driverConfig, pluginConfig);
|
|
85
|
+
return {} as InitResult<Cmd>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private async parsePreConfigArgs<
|
|
89
|
+
Cmd extends CliCommand,
|
|
90
|
+
SubCmd extends CliExtensionSubcommand | CliCommandSetupSubcommand | void,
|
|
91
|
+
>(args?: Args<Cmd, SubCmd>): Promise<{preConfigArgs: PreConfigArgs; throwInsteadOfExit: boolean}> {
|
|
92
|
+
const parser = await getParser();
|
|
93
|
+
let throwInsteadOfExit = false;
|
|
94
|
+
|
|
95
|
+
if (args) {
|
|
96
|
+
if (args.throwInsteadOfExit) {
|
|
97
|
+
throwInsteadOfExit = true;
|
|
98
|
+
delete args.throwInsteadOfExit;
|
|
99
|
+
}
|
|
100
|
+
const preConfigArgs = {...args, subcommand: args.subcommand ?? SERVER_SUBCOMMAND} as PreConfigArgs;
|
|
101
|
+
ArgParser.normalizeServerArgs(preConfigArgs);
|
|
102
|
+
return {preConfigArgs, throwInsteadOfExit};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return {preConfigArgs: parser.parseArgs() as PreConfigArgs, throwInsteadOfExit};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private assertConfigFileOk(configResult: Awaited<ReturnType<typeof readConfigFile>>): void {
|
|
109
|
+
if (!_.isEmpty(configResult.errors)) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
`Errors in config file ${configResult.filepath}:\n ${configResult.reason ?? configResult.errors}`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private async finishServerInit<Cmd extends CliCommand>(
|
|
117
|
+
preConfigArgs: PreConfigArgs,
|
|
118
|
+
configResult: Awaited<ReturnType<typeof readConfigFile>>,
|
|
119
|
+
driverConfig: ExtensionConfigs['driverConfig'],
|
|
120
|
+
pluginConfig: ExtensionConfigs['pluginConfig'],
|
|
121
|
+
appiumHome: string,
|
|
122
|
+
appiumHomeSourceName: string,
|
|
123
|
+
): Promise<InitResult<Cmd>> {
|
|
124
|
+
const defaults = getDefaultsForSchema(false);
|
|
125
|
+
const serverArgs = _.defaultsDeep(
|
|
126
|
+
{},
|
|
127
|
+
preConfigArgs,
|
|
128
|
+
configResult.config?.server,
|
|
129
|
+
defaults,
|
|
130
|
+
) as ParsedArgs<CliCommandServer>;
|
|
131
|
+
|
|
132
|
+
if (preConfigArgs.showConfig) {
|
|
133
|
+
showConfig(getNonDefaultServerArgs(preConfigArgs as Args), configResult, defaults, serverArgs);
|
|
134
|
+
return {} as InitResult<Cmd>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (preConfigArgs.showDebugInfo) {
|
|
138
|
+
await showDebugInfo({
|
|
139
|
+
driverConfig,
|
|
140
|
+
pluginConfig,
|
|
141
|
+
appiumHome,
|
|
142
|
+
});
|
|
143
|
+
return {} as InitResult<Cmd>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
await logsinkInit(serverArgs);
|
|
147
|
+
await this.applyLogFilters(serverArgs);
|
|
148
|
+
|
|
149
|
+
if (!serverArgs.noPermsCheck) {
|
|
150
|
+
await requireDir(appiumHome, true, appiumHomeSourceName);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const appiumDriver = new AppiumDriver(serverArgs as DriverOpts<AppiumDriverConstraints>);
|
|
154
|
+
appiumDriver.driverConfig = driverConfig;
|
|
155
|
+
await preflightChecks(serverArgs, this.throwInsteadOfExit);
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
appiumDriver,
|
|
159
|
+
parsedArgs: serverArgs,
|
|
160
|
+
driverConfig,
|
|
161
|
+
pluginConfig,
|
|
162
|
+
appiumHome,
|
|
163
|
+
} as InitResult<Cmd>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private async applyLogFilters(serverArgs: ParsedArgs<CliCommandServer>): Promise<void> {
|
|
167
|
+
if (!serverArgs.logFilters) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const {issues, rules} = await logger.unwrap().loadSecureValuesPreprocessingRules(serverArgs.logFilters);
|
|
171
|
+
const argToLog = _.truncate(JSON.stringify(serverArgs.logFilters), {
|
|
172
|
+
length: 150,
|
|
173
|
+
});
|
|
174
|
+
if (!_.isEmpty(issues)) {
|
|
175
|
+
throw new Error(
|
|
176
|
+
`The log filtering rules config ${argToLog} has issues: ` + JSON.stringify(issues, null, 2),
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
if (_.isEmpty(rules)) {
|
|
180
|
+
logger.warn(
|
|
181
|
+
`Found no log filtering rules in the ${argToLog} config. ` + `Is that expected?`,
|
|
182
|
+
);
|
|
183
|
+
} else {
|
|
184
|
+
logger.info(`Loaded ${util.pluralize('filtering rule', rules.length, true)}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private async runExtensionCliIfNeeded(
|
|
189
|
+
preConfigArgs: PreConfigArgs,
|
|
190
|
+
driverConfig: ExtensionConfigs['driverConfig'],
|
|
191
|
+
pluginConfig: ExtensionConfigs['pluginConfig'],
|
|
192
|
+
): Promise<void> {
|
|
193
|
+
if (!isExtensionCommandArgs(preConfigArgs)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (isDriverCommandArgs(preConfigArgs)) {
|
|
197
|
+
await runExtensionCommand(preConfigArgs, driverConfig);
|
|
198
|
+
}
|
|
199
|
+
if (isPluginCommandArgs(preConfigArgs)) {
|
|
200
|
+
await runExtensionCommand(preConfigArgs, pluginConfig);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (isDriverCommandArgs(preConfigArgs) || isPluginCommandArgs(preConfigArgs)) {
|
|
204
|
+
const cmd = isDriverCommandArgs(preConfigArgs)
|
|
205
|
+
? preConfigArgs.driverCommand
|
|
206
|
+
: preConfigArgs.pluginCommand;
|
|
207
|
+
if (cmd === 'install') {
|
|
208
|
+
await injectAppiumSymlinks(driverConfig, pluginConfig, logger);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import {log as logger} from '../logger';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import type {AppiumServer} from '@appium/types';
|
|
4
|
+
import {getActivePlugins, getActiveDrivers} from '../extension';
|
|
5
|
+
import registerNode from './grid-v3-register';
|
|
6
|
+
import {
|
|
7
|
+
determineAppiumHomeSource,
|
|
8
|
+
logStartupInfo,
|
|
9
|
+
buildServerOpts,
|
|
10
|
+
createAppiumServer,
|
|
11
|
+
logServerAddress,
|
|
12
|
+
} from './main-helpers';
|
|
13
|
+
import type {InitResult, ServerInitData} from './init-types';
|
|
14
|
+
import type {
|
|
15
|
+
Args,
|
|
16
|
+
CliCommand,
|
|
17
|
+
CliCommandServer,
|
|
18
|
+
CliCommandSetupSubcommand,
|
|
19
|
+
CliExtensionSubcommand,
|
|
20
|
+
} from 'appium/types';
|
|
21
|
+
import type {ServerOpts} from '@appium/base-driver';
|
|
22
|
+
import net from 'node:net';
|
|
23
|
+
|
|
24
|
+
const MAX_SERVER_PROCESS_LISTENERS = 100;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Starts the Appium HTTP server after {@link AppiumInitializer.init}: loads drivers/plugins, binds, grid register, signals.
|
|
28
|
+
*/
|
|
29
|
+
export class AppiumMainRunner {
|
|
30
|
+
/**
|
|
31
|
+
* For server init: builds listeners, registers with Grid 3 if configured, and returns the server.
|
|
32
|
+
* For non-server commands, `initResult` is empty and this resolves to `undefined`.
|
|
33
|
+
*
|
|
34
|
+
* @param initResult - Output of {@link AppiumInitializer.init}
|
|
35
|
+
* @param args - Original args (used to describe `appiumHome` source in logs)
|
|
36
|
+
*/
|
|
37
|
+
async run<
|
|
38
|
+
Cmd extends CliCommand = CliCommandServer,
|
|
39
|
+
SubCmd extends CliExtensionSubcommand | CliCommandSetupSubcommand | void = void,
|
|
40
|
+
>(initResult: InitResult<Cmd>, args?: Args<Cmd, SubCmd>): Promise<Cmd extends CliCommandServer ? AppiumServer : void> {
|
|
41
|
+
if (_.isEmpty(initResult)) {
|
|
42
|
+
return undefined as Cmd extends CliCommandServer ? AppiumServer : void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const {appiumDriver, pluginConfig, driverConfig, parsedArgs, appiumHome} = initResult as ServerInitData;
|
|
46
|
+
|
|
47
|
+
const pluginClasses = await getActivePlugins(
|
|
48
|
+
pluginConfig,
|
|
49
|
+
parsedArgs.pluginsImportChunkSize,
|
|
50
|
+
parsedArgs.usePlugins,
|
|
51
|
+
);
|
|
52
|
+
for (const [pluginClass, name] of pluginClasses) {
|
|
53
|
+
appiumDriver.pluginClasses.set(pluginClass, name);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await logStartupInfo(parsedArgs);
|
|
57
|
+
|
|
58
|
+
appiumDriver.configureGlobalFeatures();
|
|
59
|
+
|
|
60
|
+
const appiumHomeSourceName = determineAppiumHomeSource(args?.appiumHome);
|
|
61
|
+
logger.debug(`The ${appiumHomeSourceName}: ${appiumHome}`);
|
|
62
|
+
|
|
63
|
+
const driverClasses = await getActiveDrivers(
|
|
64
|
+
driverConfig,
|
|
65
|
+
parsedArgs.driversImportChunkSize,
|
|
66
|
+
parsedArgs.useDrivers,
|
|
67
|
+
);
|
|
68
|
+
const {serverOpts, normalizedBasePath} = buildServerOpts(
|
|
69
|
+
appiumDriver,
|
|
70
|
+
parsedArgs,
|
|
71
|
+
driverClasses,
|
|
72
|
+
pluginClasses,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const server = await this.startHttpServer(serverOpts, appiumDriver, normalizedBasePath);
|
|
76
|
+
if (!server) {
|
|
77
|
+
return undefined as Cmd extends CliCommandServer ? AppiumServer : void;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.warnIfCorsEnabled(parsedArgs);
|
|
81
|
+
appiumDriver.server = server;
|
|
82
|
+
|
|
83
|
+
await this.registerGridOrClose(server, parsedArgs, normalizedBasePath);
|
|
84
|
+
this.attachSignalHandlers(appiumDriver, server);
|
|
85
|
+
this.logListeningUrl(server, parsedArgs, normalizedBasePath);
|
|
86
|
+
|
|
87
|
+
driverConfig.print();
|
|
88
|
+
pluginConfig.print([...pluginClasses.values()]);
|
|
89
|
+
|
|
90
|
+
return server as Cmd extends CliCommandServer ? AppiumServer : void;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private async startHttpServer(
|
|
94
|
+
serverOpts: ServerOpts,
|
|
95
|
+
appiumDriver: ServerInitData['appiumDriver'],
|
|
96
|
+
normalizedBasePath: string,
|
|
97
|
+
): Promise<AppiumServer | undefined> {
|
|
98
|
+
try {
|
|
99
|
+
return await createAppiumServer(serverOpts, appiumDriver, normalizedBasePath);
|
|
100
|
+
} catch (err: unknown) {
|
|
101
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
102
|
+
const stack = err instanceof Error ? err.stack : undefined;
|
|
103
|
+
logger.error(
|
|
104
|
+
`Could not configure Appium server. It's possible that a driver or plugin tried ` +
|
|
105
|
+
`to update the server and failed. Original error: ${message}`,
|
|
106
|
+
);
|
|
107
|
+
logger.debug(stack);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private warnIfCorsEnabled(parsedArgs: ServerInitData['parsedArgs']): void {
|
|
114
|
+
if (parsedArgs.allowCors) {
|
|
115
|
+
logger.warn(
|
|
116
|
+
'You have enabled CORS requests from any host. Be careful not ' +
|
|
117
|
+
'to visit sites which could maliciously try to start Appium ' +
|
|
118
|
+
'sessions on your machine',
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private async registerGridOrClose(
|
|
124
|
+
server: AppiumServer,
|
|
125
|
+
parsedArgs: ServerInitData['parsedArgs'],
|
|
126
|
+
normalizedBasePath: string,
|
|
127
|
+
): Promise<void> {
|
|
128
|
+
try {
|
|
129
|
+
if (parsedArgs.nodeconfig) {
|
|
130
|
+
await registerNode(
|
|
131
|
+
parsedArgs.nodeconfig,
|
|
132
|
+
parsedArgs.address,
|
|
133
|
+
parsedArgs.port,
|
|
134
|
+
normalizedBasePath,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
} catch (err: unknown) {
|
|
138
|
+
await server.close();
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private attachSignalHandlers(
|
|
144
|
+
appiumDriver: ServerInitData['appiumDriver'],
|
|
145
|
+
server: AppiumServer,
|
|
146
|
+
): void {
|
|
147
|
+
process.setMaxListeners(MAX_SERVER_PROCESS_LISTENERS);
|
|
148
|
+
for (const signal of ['SIGINT', 'SIGTERM'] as const) {
|
|
149
|
+
process.once(signal, async function onSignal() {
|
|
150
|
+
logger.info(`Received ${signal} - shutting down`);
|
|
151
|
+
try {
|
|
152
|
+
await appiumDriver.shutdown(`The process has received ${signal} signal`);
|
|
153
|
+
await server.close();
|
|
154
|
+
process.exit(0);
|
|
155
|
+
} catch (e: unknown) {
|
|
156
|
+
logger.warn(e);
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private logListeningUrl(
|
|
164
|
+
server: AppiumServer,
|
|
165
|
+
parsedArgs: ServerInitData['parsedArgs'],
|
|
166
|
+
normalizedBasePath: string,
|
|
167
|
+
): void {
|
|
168
|
+
const protocol = server.isSecure() ? 'https' : 'http';
|
|
169
|
+
const address = net.isIPv6(parsedArgs.address) ? `[${parsedArgs.address}]` : parsedArgs.address;
|
|
170
|
+
logServerAddress(`${protocol}://${address}:${parsedArgs.port}${normalizedBasePath}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type {IOutputError} from '@sidvind/better-ajv-errors';
|
|
2
|
+
import type {ErrorObject, SchemaObject} from 'ajv';
|
|
3
|
+
import {lilconfig, type LoaderSync, type LilconfigResult} from 'lilconfig';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import * as yaml from 'yaml';
|
|
6
|
+
import type {AppiumConfig, NormalizedAppiumConfig} from '@appium/types';
|
|
7
|
+
import {getSchema, validate} from '../schema/schema';
|
|
8
|
+
import {formatErrors} from '../schema/format-errors';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A cache of the raw config file (a JSON string) at a filepath.
|
|
12
|
+
* This is used for better error reporting.
|
|
13
|
+
* Note that config files needn't be JSON, but it helps if they are.
|
|
14
|
+
*/
|
|
15
|
+
const rawConfig = new Map<string, string>();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Result of calling {@link readConfigFile}.
|
|
19
|
+
*/
|
|
20
|
+
export interface ReadConfigFileResult {
|
|
21
|
+
errors?: ErrorObject[];
|
|
22
|
+
filepath?: string;
|
|
23
|
+
isEmpty?: boolean;
|
|
24
|
+
config?: NormalizedAppiumConfig;
|
|
25
|
+
reason?: string | IOutputError[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Options for {@link readConfigFile}.
|
|
30
|
+
*/
|
|
31
|
+
export interface ReadConfigFileOptions {
|
|
32
|
+
pretty?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* This is an `AsyncSearcher` which is inexplicably _not_ exported by the `lilconfig` type definition.
|
|
37
|
+
*/
|
|
38
|
+
type LilconfigAsyncSearcher = ReturnType<typeof lilconfig>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Given an optional path, read a config file. Validates the config file.
|
|
42
|
+
*
|
|
43
|
+
* Call {@link validate} if you already have a config object.
|
|
44
|
+
* @public
|
|
45
|
+
* @param filepath - Explicit config path; when omitted, searches with lilconfig
|
|
46
|
+
* @param opts - e.g. `pretty` for formatted validation errors
|
|
47
|
+
* @returns Contains config and filepath, if found, and any errors
|
|
48
|
+
*/
|
|
49
|
+
export async function readConfigFile(
|
|
50
|
+
filepath?: string,
|
|
51
|
+
opts: ReadConfigFileOptions = {}
|
|
52
|
+
): Promise<ReadConfigFileResult> {
|
|
53
|
+
const lc = lilconfig('appium', {
|
|
54
|
+
loaders: {
|
|
55
|
+
'.yaml': yamlLoader as LoaderSync,
|
|
56
|
+
'.yml': yamlLoader as LoaderSync,
|
|
57
|
+
'.json': jsonLoader as LoaderSync,
|
|
58
|
+
noExt: jsonLoader as LoaderSync,
|
|
59
|
+
},
|
|
60
|
+
packageProp: 'appiumConfig',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const result = filepath ? await loadConfigFile(lc, filepath) : await searchConfigFile(lc);
|
|
64
|
+
|
|
65
|
+
if (result?.filepath && !result?.isEmpty) {
|
|
66
|
+
const {pretty = true} = opts;
|
|
67
|
+
try {
|
|
68
|
+
let configResult: ReadConfigFileResult;
|
|
69
|
+
const errors = validate(result.config) as ErrorObject[];
|
|
70
|
+
if (_.isEmpty(errors)) {
|
|
71
|
+
configResult = {...result, errors};
|
|
72
|
+
} else {
|
|
73
|
+
const reason = formatErrors(errors, result.config as Record<string, unknown>, {
|
|
74
|
+
json: rawConfig.get(result.filepath),
|
|
75
|
+
pretty,
|
|
76
|
+
});
|
|
77
|
+
configResult = reason ? {...result, errors, reason} : {...result, errors};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// normalize (to camel case) all top-level property names of the config file
|
|
81
|
+
configResult.config = normalizeConfig(configResult.config as AppiumConfig);
|
|
82
|
+
|
|
83
|
+
return configResult;
|
|
84
|
+
} finally {
|
|
85
|
+
// clean up the raw config file cache, which is only kept to better report errors.
|
|
86
|
+
rawConfig.delete(result.filepath);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return result ?? {};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Converts schema property names to either the `appiumCliDest` value, if any, or camelCase.
|
|
94
|
+
*
|
|
95
|
+
* @param config - Raw config object as parsed from file
|
|
96
|
+
* @returns New object with camel-cased keys (or CLI `dest` keys).
|
|
97
|
+
*/
|
|
98
|
+
export function normalizeConfig(config: AppiumConfig): NormalizedAppiumConfig {
|
|
99
|
+
const schema = getSchema();
|
|
100
|
+
|
|
101
|
+
const isSchemaTypeObject = (schemaObj: SchemaObject | Record<string, unknown> | undefined): boolean =>
|
|
102
|
+
Boolean((schemaObj as SchemaObject | undefined)?.properties || (schemaObj as SchemaObject | undefined)?.type === 'object');
|
|
103
|
+
|
|
104
|
+
const normalize = (rootConfig: AppiumConfig, section?: string): Record<string, unknown> => {
|
|
105
|
+
const obj = _.isUndefined(section)
|
|
106
|
+
? rootConfig
|
|
107
|
+
: (_.get(rootConfig, section, rootConfig) as Record<string, unknown>);
|
|
108
|
+
|
|
109
|
+
const mappedObj = _.mapKeys(obj, (_v, prop) =>
|
|
110
|
+
_.get(schema, `properties.server.properties[${prop}].appiumCliDest`, _.camelCase(prop))
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return _.mapValues(mappedObj, (value, property) => {
|
|
114
|
+
const nextSection = section ? `${section}.${property}` : property;
|
|
115
|
+
return isSchemaTypeObject((schema as any).properties?.[property])
|
|
116
|
+
? normalize(rootConfig, nextSection)
|
|
117
|
+
: value;
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return normalize(config) as NormalizedAppiumConfig;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* lilconfig loader to handle `.yaml` files
|
|
126
|
+
*/
|
|
127
|
+
function yamlLoader(filepath: string, content: string): unknown {
|
|
128
|
+
try {
|
|
129
|
+
return yaml.parse(content);
|
|
130
|
+
} catch (e) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`The YAML config at '${filepath}' cannot be loaded. Original error: ${(e as Error).message}`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Custom JSON loader that caches the raw config file (for use with `better-ajv-errors`).
|
|
139
|
+
* If it weren't for this cache, this would be unnecessary.
|
|
140
|
+
*/
|
|
141
|
+
function jsonLoader(filepath: string, content: string): unknown {
|
|
142
|
+
rawConfig.set(filepath, content);
|
|
143
|
+
try {
|
|
144
|
+
return JSON.parse(content);
|
|
145
|
+
} catch (e) {
|
|
146
|
+
rawConfig.delete(filepath);
|
|
147
|
+
throw new Error(
|
|
148
|
+
`The JSON config at '${filepath}' cannot be loaded. Original error: ${(e as Error).message}`
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Loads a config file from an explicit path
|
|
155
|
+
*/
|
|
156
|
+
async function loadConfigFile(lc: LilconfigAsyncSearcher, filepath: string): Promise<LilconfigResult> {
|
|
157
|
+
try {
|
|
158
|
+
// removing "await" will cause any rejection to _not_ be caught in this block!
|
|
159
|
+
return await lc.load(filepath);
|
|
160
|
+
} catch (err) {
|
|
161
|
+
if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
162
|
+
(err as NodeJS.ErrnoException).message = `Config file not found at user-provided path: ${filepath}`;
|
|
163
|
+
throw err;
|
|
164
|
+
} else if (err instanceof SyntaxError) {
|
|
165
|
+
// generally invalid JSON
|
|
166
|
+
err.message = `Config file at user-provided path ${filepath} is invalid:\n${err.message}`;
|
|
167
|
+
throw err;
|
|
168
|
+
}
|
|
169
|
+
throw err;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Searches for a config file
|
|
175
|
+
*/
|
|
176
|
+
async function searchConfigFile(lc: LilconfigAsyncSearcher): Promise<LilconfigResult> {
|
|
177
|
+
return await lc.search();
|
|
178
|
+
}
|