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
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
|
+
}
|
|
@@ -1,48 +1,49 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type {IOutputError} from '@sidvind/better-ajv-errors';
|
|
2
2
|
import type {ErrorObject, SchemaObject} from 'ajv';
|
|
3
3
|
import {lilconfig, type LoaderSync, type LilconfigResult} from 'lilconfig';
|
|
4
4
|
import _ from 'lodash';
|
|
5
5
|
import * as yaml from 'yaml';
|
|
6
6
|
import type {AppiumConfig, NormalizedAppiumConfig} from '@appium/types';
|
|
7
|
-
import {getSchema, validate} from '
|
|
7
|
+
import {getSchema, validate} from '../schema/schema';
|
|
8
|
+
import {formatErrors} from '../schema/format-errors';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* A cache of the raw config file (a JSON string) at a filepath.
|
|
11
12
|
* This is used for better error reporting.
|
|
12
13
|
* Note that config files needn't be JSON, but it helps if they are.
|
|
13
14
|
*/
|
|
14
|
-
const rawConfig = new Map<string,
|
|
15
|
+
const rawConfig = new Map<string, string>();
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
|
-
*
|
|
18
|
-
* helpful string for the user.
|
|
19
|
-
*
|
|
20
|
-
* - If `opts` contains a `json` property, this should be the original JSON
|
|
21
|
-
* _string_ of the config file. This is only applicable if the config file
|
|
22
|
-
* was in JSON format. If present, it will associate line numbers with errors.
|
|
23
|
-
* - If `errors` happens to be empty, this will throw.
|
|
24
|
-
*
|
|
25
|
-
* @throws {TypeError} If `errors` is empty
|
|
18
|
+
* Result of calling {@link readConfigFile}.
|
|
26
19
|
*/
|
|
27
|
-
export
|
|
28
|
-
errors
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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;
|
|
39
33
|
}
|
|
40
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
|
+
|
|
41
40
|
/**
|
|
42
41
|
* Given an optional path, read a config file. Validates the config file.
|
|
43
42
|
*
|
|
44
43
|
* Call {@link validate} if you already have a config object.
|
|
45
44
|
* @public
|
|
45
|
+
* @param filepath - Explicit config path; when omitted, searches with lilconfig
|
|
46
|
+
* @param opts - e.g. `pretty` for formatted validation errors
|
|
46
47
|
* @returns Contains config and filepath, if found, and any errors
|
|
47
48
|
*/
|
|
48
49
|
export async function readConfigFile(
|
|
@@ -89,8 +90,10 @@ export async function readConfigFile(
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
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).
|
|
94
97
|
*/
|
|
95
98
|
export function normalizeConfig(config: AppiumConfig): NormalizedAppiumConfig {
|
|
96
99
|
const schema = getSchema();
|
|
@@ -173,40 +176,3 @@ async function loadConfigFile(lc: LilconfigAsyncSearcher, filepath: string): Pro
|
|
|
173
176
|
async function searchConfigFile(lc: LilconfigAsyncSearcher): Promise<LilconfigResult> {
|
|
174
177
|
return await lc.search();
|
|
175
178
|
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Result of calling {@link readConfigFile}.
|
|
179
|
-
*/
|
|
180
|
-
export interface ReadConfigFileResult {
|
|
181
|
-
errors?: ErrorObject[];
|
|
182
|
-
filepath?: string;
|
|
183
|
-
isEmpty?: boolean;
|
|
184
|
-
config?: NormalizedAppiumConfig;
|
|
185
|
-
reason?: string | IOutputError[];
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Options for {@link readConfigFile}.
|
|
190
|
-
*/
|
|
191
|
-
export interface ReadConfigFileOptions {
|
|
192
|
-
pretty?: boolean;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* The string should be a raw JSON string.
|
|
197
|
-
*/
|
|
198
|
-
export type RawJson = string;
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Options for {@link formatErrors}.
|
|
202
|
-
*/
|
|
203
|
-
export interface FormatConfigErrorsOptions {
|
|
204
|
-
json?: RawJson;
|
|
205
|
-
pretty?: boolean;
|
|
206
|
-
schemaId?: string;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* This is an `AsyncSearcher` which is inexplicably _not_ exported by the `lilconfig` type definition.
|
|
211
|
-
*/
|
|
212
|
-
type LilconfigAsyncSearcher = ReturnType<typeof lilconfig>;
|
|
@@ -2,7 +2,7 @@ import axios from 'axios';
|
|
|
2
2
|
import {fs} from '@appium/support';
|
|
3
3
|
import type {StringRecord} from '@appium/types';
|
|
4
4
|
import _ from 'lodash';
|
|
5
|
-
import logger from '
|
|
5
|
+
import {log as logger} from '../logger';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Selenium **Grid 3** (legacy hub) node integration.
|
|
@@ -18,6 +18,40 @@ import logger from './logger';
|
|
|
18
18
|
const GRID_V3_REGISTER_PATH = '/grid/register';
|
|
19
19
|
const GRID_V3_PROXY_API_PATH = '/grid/api/proxy';
|
|
20
20
|
|
|
21
|
+
interface Grid3HubConfiguration {
|
|
22
|
+
hubProtocol?: string;
|
|
23
|
+
hubHost?: string;
|
|
24
|
+
hubPort?: number;
|
|
25
|
+
url?: string;
|
|
26
|
+
host?: string;
|
|
27
|
+
port?: number;
|
|
28
|
+
id?: string;
|
|
29
|
+
register?: boolean;
|
|
30
|
+
registerCycle?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface Grid3NodeConfig extends StringRecord {
|
|
34
|
+
configuration?: Grid3HubConfiguration;
|
|
35
|
+
capabilities?: unknown;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface Grid3ProxyApiResponse {
|
|
39
|
+
success: boolean;
|
|
40
|
+
msg?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default async function registerNode(
|
|
44
|
+
data: string,
|
|
45
|
+
addr: string,
|
|
46
|
+
port: number,
|
|
47
|
+
basePath: string
|
|
48
|
+
): Promise<void>;
|
|
49
|
+
export default async function registerNode(
|
|
50
|
+
data: Grid3NodeConfig,
|
|
51
|
+
addr?: string,
|
|
52
|
+
port?: number,
|
|
53
|
+
basePath?: string
|
|
54
|
+
): Promise<void>;
|
|
21
55
|
/**
|
|
22
56
|
* Registers this server as a node with a **Selenium Grid 3** hub.
|
|
23
57
|
*
|
|
@@ -33,18 +67,6 @@ const GRID_V3_PROXY_API_PATH = '/grid/api/proxy';
|
|
|
33
67
|
* @param port - Bind to this port
|
|
34
68
|
* @param basePath - Base path for the Appium server (used in the node URL sent to the hub; may be `''`)
|
|
35
69
|
*/
|
|
36
|
-
export default async function registerNode(
|
|
37
|
-
data: string,
|
|
38
|
-
addr: string,
|
|
39
|
-
port: number,
|
|
40
|
-
basePath: string
|
|
41
|
-
): Promise<void>;
|
|
42
|
-
export default async function registerNode(
|
|
43
|
-
data: Grid3NodeConfig,
|
|
44
|
-
addr?: string,
|
|
45
|
-
port?: number,
|
|
46
|
-
basePath?: string
|
|
47
|
-
): Promise<void>;
|
|
48
70
|
export default async function registerNode(
|
|
49
71
|
data: string | Grid3NodeConfig,
|
|
50
72
|
addr?: string,
|
|
@@ -226,25 +248,3 @@ async function isAlreadyRegistered(configHolder: Grid3NodeConfig): Promise<boole
|
|
|
226
248
|
logger.debug(`Selenium Grid 3 hub down or not responding: ${(err as Error).message}`);
|
|
227
249
|
}
|
|
228
250
|
}
|
|
229
|
-
|
|
230
|
-
interface Grid3HubConfiguration {
|
|
231
|
-
hubProtocol?: string;
|
|
232
|
-
hubHost?: string;
|
|
233
|
-
hubPort?: number;
|
|
234
|
-
url?: string;
|
|
235
|
-
host?: string;
|
|
236
|
-
port?: number;
|
|
237
|
-
id?: string;
|
|
238
|
-
register?: boolean;
|
|
239
|
-
registerCycle?: number;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
interface Grid3NodeConfig extends StringRecord {
|
|
243
|
-
configuration?: Grid3HubConfiguration;
|
|
244
|
-
capabilities?: unknown;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
interface Grid3ProxyApiResponse {
|
|
248
|
-
success: boolean;
|
|
249
|
-
msg?: string;
|
|
250
|
-
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type {AppiumDriver} from '../appium';
|
|
2
|
+
import type {
|
|
3
|
+
Args,
|
|
4
|
+
CliCommand,
|
|
5
|
+
CliCommandServer,
|
|
6
|
+
CliCommandSetupSubcommand,
|
|
7
|
+
CliExtensionSubcommand,
|
|
8
|
+
ParsedArgs,
|
|
9
|
+
} from 'appium/types';
|
|
10
|
+
import type {ExtensionConfigs} from '../extension';
|
|
11
|
+
|
|
12
|
+
/** Empty object returned when `init` completes for non-server CLI flows (extension/setup). */
|
|
13
|
+
export type ExtCommandInitResult = Record<string, never>;
|
|
14
|
+
|
|
15
|
+
/** Driver/plugin config plus server instance and merged server args after successful server `init`. */
|
|
16
|
+
export type ServerInitData = ExtensionConfigs & {
|
|
17
|
+
appiumDriver: AppiumDriver;
|
|
18
|
+
parsedArgs: ParsedArgs<CliCommandServer>;
|
|
19
|
+
appiumHome: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Discriminated by CLI command: server subcommand yields {@link ServerInitData}; otherwise {@link ExtCommandInitResult}. */
|
|
23
|
+
export type InitResult<Cmd extends CliCommand = CliCommandServer> = Cmd extends CliCommandServer
|
|
24
|
+
? ServerInitData
|
|
25
|
+
: ExtCommandInitResult;
|
|
26
|
+
|
|
27
|
+
/** CLI + programmatic args before `init` narrows by `subcommand`. */
|
|
28
|
+
export type PreConfigArgs = Args<
|
|
29
|
+
CliCommand,
|
|
30
|
+
CliExtensionSubcommand | CliCommandSetupSubcommand | void
|
|
31
|
+
>;
|