Files
appium/packages/base-plugin/lib/plugin.js

108 lines
3.4 KiB
JavaScript

import {ExtensionCore, generateDriverLogPrefix, validateExecuteMethodParams} from '@appium/base-driver';
/**
* @implements {Plugin}
*/
class BasePlugin extends ExtensionCore {
/**
* @deprecated Use this.log instead of this.logger
* @type {import('@appium/types').AppiumLogger}
*/
logger;
/**
* Subclasses should use type `import('@appium/types').MethodMap<SubclassName>`.
*
* This will verify that the commands in the `newMethodMap` property are
* valid. It is impossible to use a generic type param here; the type of this should really
* be something like `MethodMap<T extends BasePlugin>` but that isn't a thing TS does.
*
* ```ts
* static newMethodMap = {
* '/session/:sessionId/fake_data': {
* GET: {command: 'getFakeSessionData', neverProxy: true},
* }
* } as const;
* ```
*/
static newMethodMap = {};
/**
* Subclasses should use type `import('@appium/types').ExecuteMethodMap<SubclassName>`.
*
* Building up this map allows the use of the convenience function `executeMethod`, which
* basically does verification of names and parameters for execute methods implemented by this
* plugin.
*
* ```ts
* static executeMethodMap = {
* 'foo: bar': {
* command: 'commandName',
* params: {required: ['thing1', 'thing2'], optional: ['thing3']},
* },
* } as const;
* ```
*/
static executeMethodMap = {};
/**
* @param {string} name
* @param {Record<string,unknown>} [cliArgs]
* @param {string|null} driverId
*/
constructor(name, cliArgs = {}, driverId = null) {
super();
if (driverId) {
this.updateLogPrefix(`${generateDriverLogPrefix(this)} <${driverId}>`);
}
this.name = name;
this.cliArgs = cliArgs;
this.logger = this.log;
}
/**
* A convenience method that can be called by plugins who implement their own `executeMethodMap`.
* Only useful if your plugin has defined `executeMethodMap`. This helper requires passing in the
* `next` and `driver` objects since naturally we'd want to make sure to trigger the driver's own
* `executeMethod` call if an execute method is not found on the plugin itself.
*
* @template {Constraints} C
* @param {NextPluginCallback} next
* @param {Driver<C>} driver
* @param {string} script
* @param {readonly [import('@appium/types').StringRecord<unknown>] | readonly any[]} protoArgs
*/
async executeMethod(next, driver, script, protoArgs) {
const Plugin = /** @type {import('@appium/types').PluginClass<Plugin>} */ (this.constructor);
const commandMetadata = {...Plugin.executeMethodMap?.[script]};
if (!commandMetadata.command || !(commandMetadata.command in this)) {
this.logger.info(
`Plugin did not know how to handle method '${script}'. Passing control to next`
);
return await next();
}
const command = /** @type {import('@appium/types').PluginCommand<Driver<C>>} */ (
this[commandMetadata.command]
);
const args = validateExecuteMethodParams(/** @type {any[]} */ (protoArgs), commandMetadata.params);
return await command.call(this, next, driver, ...args);
}
}
export default BasePlugin;
export {BasePlugin};
/**
* @typedef {import('@appium/types').Plugin} Plugin
* @typedef {import('@appium/types').NextPluginCallback} NextPluginCallback
* @typedef {import('@appium/types').Constraints} Constraints
*/
/**
* @template {Constraints} C
* @typedef {import('@appium/types').Driver<C>} Driver
*/