import type { EventEmitter } from 'node:events';
import type { Merge } from 'type-fest';
import type { Capabilities, DriverCaps, W3CCapabilities } from './capabilities';
import type { BidiModuleMap, BiDiResultData, ExecuteMethodMap, MethodMap } from './command-maps';
import type { DefaultCreateSessionResult, DefaultDeleteSessionResult, DriverData, EventHistory, IImplementedCommands, IWDClassicCommands, IAppiumCommands, IJSONWPCommands, IMJSONWPCommands, IOtherProtocolCommands } from './commands';
import type { Constraints } from './constraints';
import type { ServerArgs } from './config';
import type { HTTPHeaders, HTTPMethod } from './http';
import type { AppiumLogger } from './logger';
import type { AppiumServer, UpdateServerCallback } from './server';
import type { Class, StringRecord } from './util';
import type internal from 'node:stream';
/**
 * Interface implemented by the `DeviceSettings` class in `@appium/base-driver`
 */
export interface IDeviceSettings<T extends StringRecord> {
    update(newSettings: T): Promise<void>;
    getSettings(): T;
}
export interface DriverHelpers {
    configureApp: (app: string, supportedAppExtensions?: string | string[] | ConfigureAppOptions) => Promise<string>;
    isPackageOrBundle: (app: string) => boolean;
    duplicateKeys: <T>(input: T, firstKey: string, secondKey: string) => T;
    parseCapsArray: (cap: string | string[]) => string[];
    generateDriverLogPrefix: (obj: object, sessionId?: string) => string;
}
export type SettingsUpdateListener<T extends Record<string, unknown> = Record<string, unknown>> = (prop: keyof T, newValue: unknown, curValue: unknown) => Promise<void>;
export type Protocol = 'MJSONWP' | 'W3C';
/**
 * Methods and properties which both `AppiumDriver` and `BaseDriver` inherit.
 *
 * This should not be used directly by external code.
 */
export interface Core<C extends Constraints, Settings extends StringRecord = StringRecord> {
    shouldValidateCaps: boolean;
    sessionId: string | null;
    sessionCreationTimestampMs: number;
    opts: DriverOpts<C>;
    initialOpts: InitialOpts;
    protocol?: Protocol;
    helpers: DriverHelpers;
    basePath: string;
    relaxedSecurityEnabled: boolean;
    allowInsecure: string[];
    denyInsecure: string[];
    newCommandTimeoutMs: number;
    implicitWaitMs: number;
    locatorStrategies: string[];
    webLocatorStrategies: string[];
    eventEmitter: EventEmitter;
    settings: IDeviceSettings<Settings>;
    log: AppiumLogger;
    driverData: DriverData;
    isCommandsQueueEnabled: boolean;
    eventHistory: EventHistory;
    bidiEventSubs: Record<string, string[]>;
    updateBidiCommands(cmds: BidiModuleMap): void;
    onUnexpectedShutdown(handler: () => any): void;
    /**
     * @summary Retrieve the server's current status.
     * @description
     * Returns information about whether a remote end is in a state in which it can create new sessions and can additionally include arbitrary meta information that is specific to the implementation.
     *
     * The readiness state is represented by the ready property of the body, which is false if an attempt to create a session at the current time would fail. However, the value true does not guarantee that a New Session command will succeed.
     *
     * Implementations may optionally include additional meta information as part of the body, but the top-level properties ready and message are reserved and must not be overwritten.
     *
     * @example
     * ```js
     * // webdriver.io example
     * await driver.status();
     * ```
     *
     * ```python
     * driver.get_status()
     * ```
     *
     * ```java
     * driver.getStatus();
     * ```
     *
     * ```ruby
     * # ruby_lib example
     * remote_status
     *
     * # ruby_lib_core example
     * @driver.remote_status
     * ```
     */
    getStatus(): Promise<any>;
    sessionExists(sessionId?: string): boolean;
    isW3CProtocol(): boolean;
    isMjsonwpProtocol(): boolean;
    isFeatureEnabled(name: string): boolean;
    assertFeatureEnabled(name: string): void;
    validateLocatorStrategy(strategy: string, webContext?: boolean): void;
    proxyActive(sessionId?: string): boolean;
    get bidiProxyUrl(): string | null;
    getProxyAvoidList(sessionId?: string): RouteMatcher[];
    canProxy(sessionId?: string): boolean;
    proxyRouteIsAvoided(sessionId: string, method: string, url: string, body?: any): boolean;
    addManagedDriver(driver: Driver): void;
    getManagedDrivers(): Driver<Constraints>[];
    clearNewCommandTimeout(): Promise<void>;
    logEvent(eventName: string): void;
    driverForSession(sessionId: string): Core<Constraints> | null;
}
/**
 * `BaseDriver` implements this.  It contains default behavior;
 * external drivers are expected to implement {@linkcode ExternalDriver} instead.
 *
 * `C` should be the constraints of the driver.
 * `CArgs` would be the shape of `cliArgs`.
 * `Settings` is the shape of the raw device settings object (see {@linkcode IDeviceSettings})
 */
export interface Driver<C extends Constraints = Constraints, CArgs extends StringRecord = StringRecord, Settings extends StringRecord = StringRecord, CreateResult = DefaultCreateSessionResult<C>, DeleteResult = DefaultDeleteSessionResult, SessionData extends StringRecord = StringRecord> extends IImplementedCommands<C, Settings, CreateResult, DeleteResult, SessionData>, Core<C, Settings> {
    /**
     * The set of command line arguments set for this driver.
     *
     * These are derived from the Appium server configuration for this
     * particular driver (CLI flags and/or config files). They are **not**
     * user capabilities and cannot be influenced by test code.
     */
    cliArgs: CArgs;
    /**
     * The underlying HTTP server instance hosting this driver.
     *
     * This is assigned by the Appium server when a session is created.
     * It is primarily useful for advanced integrations (for example,
     * when a driver or plugin needs direct access to the web server).
     */
    server?: AppiumServer;
    /**
     * The hostname or IP address on which the Appium server is listening.
     *
     * This is assigned by the Appium server when a session is created,
     * based on the `--address` (or equivalent config) used to start the
     * server. It can be used by drivers which need to construct URLs that
     * point back to the Appium server.
     */
    serverHost?: string;
    /**
     * The TCP port on which the Appium server is listening.
     *
     * This is assigned by the Appium server when a session is created,
     * based on the `--port` (or equivalent config) used to start the
     * server. It is often used together with {@link Driver.serverHost}
     * and {@link Driver.serverPath} to build callback or proxy URLs.
     */
    serverPort?: number;
    /**
     * The base path under which WebDriver routes are exposed.
     *
     * This is assigned by the Appium server when a session is created,
     * based on the `--base-path` (or equivalent config) used to start the
     * server. For example, this might be an empty string (`''`) or
     * `'/wd/hub'`.
     */
    serverPath?: string;
    /**
     * Execute a driver (WebDriver-protocol) command by its name as defined in the routes file
     *
     * @param cmd - the name of the command
     * @param args - arguments to pass to the command
     *
     * @returns The result of running the command
     */
    executeCommand(cmd: string, ...args: any[]): Promise<any>;
    /**
     * A helper method to modify the command name before it's logged.
     *
     * Useful for resolving generic commands like 'execute' to a more specific
     * name based on arguments (e.g., identifying custom extensions).
     *
     * @param cmd - The original command name
     * @param args - Arguments passed to the command
     * @returns A potentially updated command name
     */
    clarifyCommandName?(cmd: string, args: string[]): string;
    /** Execute a driver (WebDriver Bidi protocol) command by its name as defined in the bidi commands file
     * @param bidiCmd - the name of the command in the bidi spec
     * @param args - arguments to pass to the command
     */
    executeBidiCommand(bidiCmd: string, ...args: any[]): Promise<BiDiResultData>;
    /**
     * Signify to any owning processes that this driver encountered an error which should cause the
     * session to terminate immediately (for example an upstream service failed)
     *
     * @param err - the Error object which is causing the shutdown
     */
    startUnexpectedShutdown(err?: Error): Promise<void>;
    /**
     * Start the timer for the New Command Timeout, which when it runs out, will stop the current
     * session
     */
    startNewCommandTimeout(): Promise<void>;
    /**
     * The processed capabilities used to start the session represented by the current driver instance
     */
    caps?: Capabilities<C>;
    /**
     * The original capabilities used to start the session represented by the current driver instance
     */
    originalCaps?: W3CCapabilities<C>;
    /**
     * The constraints object used to validate capabilities
     */
    desiredCapConstraints: C;
    /**
     * A helper function used to assign server information to the driver instance so the driver knows
     * where the server is Running
     *
     * @param server - the server object
     * @param host - the server hostname
     * @param port - the server port
     * @param path - the server base url
     */
    assignServer?(server: AppiumServer, host: string, port: number, path: string): void;
}
/**
 * External drivers must subclass `BaseDriver`, and can implement any methods from this interface.
 * None of these methods are implemented within Appium itself.
 */
export interface ExternalDriver<C extends Constraints = Constraints, Ctx = string, CArgs extends StringRecord = StringRecord, Settings extends StringRecord = StringRecord, CreateResult = DefaultCreateSessionResult<C>, DeleteResult = DefaultDeleteSessionResult, SessionData extends StringRecord = StringRecord> extends Driver<C, CArgs, Settings, CreateResult, DeleteResult, SessionData>, IWDClassicCommands, IAppiumCommands, IJSONWPCommands, IMJSONWPCommands<Ctx>, IOtherProtocolCommands {
    /**
     * Proxy a command to a connected WebDriver server
     *
     * @typeParam TReq - the type of the incoming body
     * @typeParam TRes - the type of the return value
     * @param url - the incoming URL
     * @param method - the incoming HTTP method
     * @param body - the incoming HTTP body
     *
     * @returns The return value of the proxied command
     */
    proxyCommand?<TReq = any, TRes = unknown>(url: string, method: HTTPMethod, body?: TReq): Promise<TRes>;
}
/**
 * Static members of a {@linkcode DriverClass}.
 *
 * This is likely unusable by external consumers, but YMMV!
 */
export interface DriverStatic<T extends Driver> {
    baseVersion: string;
    updateServer?: UpdateServerCallback;
    newMethodMap?: MethodMap<T>;
    /**
      * Drivers can define new custom bidi commands and map them to driver methods. The format must
      * be the same as that used by Appium's bidi-commands.js file, for example:
      * @example
      * {
      *   myNewBidiModule: {
      *     myNewBidiCommand: {
      *       command: 'driverMethodThatWillBeCalled',
      *       params: {
      *         required: ['requiredParam'],
      *         optional: ['optionalParam'],
      *       }
      *     }
      *   }
      * }
      */
    newBidiCommands?: BidiModuleMap;
    executeMethodMap?: ExecuteMethodMap<T>;
}
/**
 * Represents a driver class, which is used internally by Appium.
 *
 * This is likely unusable by external consumers, but YMMV!
 */
export type DriverClass<T extends Driver = Driver> = Class<T, DriverStatic<T>, [
] | [Partial<ServerArgs>] | [Partial<ServerArgs>, boolean]>;
export interface ExtraDriverOpts {
    fastReset?: boolean;
    skipUninstall?: boolean;
}
/**
 * Options as set within {@linkcode ExternalDriver.createSession}, which is a union of {@linkcode InitialOpts} and {@linkcode DriverCaps}.
 */
export type DriverOpts<C extends Constraints> = InitialOpts & DriverCaps<C>;
/**
 * Options as provided to the {@linkcode Driver} constructor.
 */
export type InitialOpts = Merge<ServerArgs, ExtraDriverOpts>;
/**
 * An instance method of a driver class, whose name may be referenced by {@linkcode MethodDef.command}, and serves as an Appium command.
 *
 * Note that this signature differs from a `PluginCommand`.
 */
export type DriverCommand<TArgs extends readonly any[] = any[], TRetval = unknown> = (...args: TArgs) => Promise<TRetval>;
/**
 * Tuple of an HTTP method with a regex matching a request path
 */
export type RouteMatcher = [HTTPMethod, RegExp];
/**
 * Result of the {@linkcode onPostProcess ConfigureAppOptions.onPostProcess} callback.
 */
export interface PostProcessResult {
    /**
     * The full past to the post-processed application package on the local file system .
     *
     * This might be a file or a folder path.
     */
    appPath: string;
}
/**
 * Information about a cached app instance.
 */
export interface CachedAppInfo {
    /**
     * SHA1 hash of the package if it is a file (and not a folder)
     */
    packageHash: string;
    /**
     * Date instance; the value of the file's `Last-Modified` header
     */
    lastModified?: Date | null;
    /**
     * The value of the file's `Etag` header
     */
    etag?: string | null;
    /**
     * `true` if the file contains an `immutable` mark in `Cache-control` header
     */
    immutable?: boolean;
    /**
     * Integer representation of `maxAge` parameter in `Cache-control` header
     */
    maxAge?: number | null;
    /**
     * The timestamp this item has been added to the cache (measured in Unix epoch milliseconds)
     */
    timestamp?: number;
    /**
     * An object containing either `file` property with SHA1 hash of the file or `folder` property
     * with total amount of cached files and subfolders
     */
    integrity?: {
        file?: string;
    } | {
        folder?: number;
    };
    /**
     * The full path to the cached app
     */
    fullPath?: string;
}
/**
 * Options for the post-processing step
 *
 * The generic can be supplied if using `axios`, where `headers` is a fancy object.
 */
export interface PostProcessOptions<Headers = HTTPHeaders> {
    /**
     * The original application url or path
     */
    originalAppLink: string;
    /**
     * The information about the previously cached app instance (if exists)
     */
    cachedAppInfo?: CachedAppInfo;
    /**
     * Whether the app has been downloaded from a remote URL
     */
    isUrl?: boolean;
    /**
     * Optional headers object.
     *
     * Only present if `isUrl` is `true` and if the server responds to `HEAD` requests. All header names are normalized to lowercase.
     */
    headers?: Headers;
    /**
     * A string containing full path to the preprocessed application package (either downloaded or a local one)
     */
    appPath?: string;
}
export interface DownloadAppOptions<Headers = HTTPHeaders> {
    /**
     * The original application url.
     */
    url: string;
    /**
     * Response headers from the download url.
     */
    headers: Headers;
    /**
     * Response stream.
     */
    stream: internal.Readable;
}
export interface ConfigureAppOptions {
    /**
     *
     * Optional function, which should be applied to the application after it is
     * downloaded/preprocessed.
     *
     * This function may be async and is expected to accept single object parameter. The function is
     * expected to either return a falsy value, which means the app must not be cached and a fresh
     * copy of it is downloaded each time, _or_ if this function returns an object containing an
     * `appPath` property, then the integrity of it will be verified and stored into the cache.
     * @returns
     */
    onPostProcess?: (obj: PostProcessOptions) => Promise<PostProcessResult | undefined> | PostProcessResult | undefined;
    /**
     * Optional function, which should be applied to the application upon download
     * progress initialization instead of the standard download handler.
     * The callback does not get invoked if the original application is not a URL.
     * It is expected that `onPostProcess` is also provided if this callback is defined.
     * Otherwise, there is a possibility the app configuration flow could be broken.
     *
     * @returns The full path to the downloaded app
     */
    onDownload?: (obj: DownloadAppOptions) => Promise<string>;
    supportedExtensions: string[];
}
//# sourceMappingURL=driver.d.ts.map