* feat: add IPC channels per session for drivers and plugins to communicate (fix#22206)
* lint
* export AppiumIpc
* fix test issues
* import AppiumIpc directly from basedriver
* fakedriver is used directly outside of appium so can't rely on existence of IPC
* make ipc functions async with lock and better types
* fix assignIpc types
* deduplicate session object deletion
* ipcGuard -> withIpc
* address various review comments
* lint
* address copilot and other review comments
* store only last message. change model to use subscription object and async generator
* enforce max message size in bytes
* fix tests and call the message payload 'data' for clarity
* lint
* make assignIpc optional on drivers for backwards compatibility
* add error handling in startClock since it is usually not awaited
* add docs
* remove todo comment
* apply copilot and eglitise suggestions
* add typedoc
* add error handling to onIpcInit
* apply more suggestions
* fix schema unit test
* apply more suggestions
* add links to ipc examples
* make minimum ipc message size 1 instead of 0
* ensure publisher names are friendly to consumers
* fix ipc message time unit
* use already included sizeof for objs
* just pass error obj to log
* be more typescriptey about our ipc guard
* make max obj size part of opts for appiumipc
* let unsubscribe return whether it worked
* improve ipc types and shapes
* apply master package-lock.json
* update schema config
* use javascript naming conventions
* clarify distinction between message and payload (data)
* ensure async iterator loop ends when unsubscribe is called
* ensure the right things happen when you unsubscribe
* make require ipc more ergonomic
* remove unnecessary async locks and de-asyncify methods
* simplify interface and just use subscriber/plugin names
* fix docs
* fix lint
* document isActive
* add note about topic namespace
* use sleep instead of delay
* restrict the ipc payload data type to something that can be cloned
* clarify topic namespacing recommendation
* make sure listeners and promises are cleaned up in async iterator
* clean up ipc internal names
* readonly
* address review comments
* make ipcmessage readonly
* readonly cause why not
* feat: allow drivers to define their own bidi commands
* test(appium): refactor plugin tests server startup
* feat: allow plugins to define their own bidi commands and events
* fix(fake-driver,fake-plugin): ensure custom bidi commands events have vendor prefixes
* feat(appium): link plugin and driver objects in log lines when possible
* fix(appium,base-driver): ensure new methods for plugins aren't called without existence checks
The first arg of `PluginCommand` is a `NextPluginCallback` which now returns `Promise<unknown>` instead of `Promise<void>`, which was incorrect.
We use `unknown` rather than `any` because it forces us to be explicit about the return value of `await next()` if we are to call it.
Added a type `DriverCommandToPluginCommand` which essentially converts a `DriverCommand` to a `PluginCommand`. It's probably best used as a type guard or decorator, but it can "fill in the blanks" when overloading commands in a plugin.
Also normalized some of the `TArgs`/`TReturn` stuff.
This changes how plugins handle CLI args:
- The `cliArgs` instance prop of a `Plugin` will never be `undefined`. If there are no args, the prop will be an empty object.
- The `cliArgs` instance prop of a `Plugin` will now contain default values, if any were provided by the `Plugin`'s schema.
This differs from how the same property is handled in drivers. To that end, I split `AppiumDriver#getCliArgsForExtension()` (previously `assignCliArgsToExtension()`) into two separate methods for clarity.
This change also contains a few associated improvements to tests and types.
This PR changes the shape of plugin classes as well as how CLI args get assigned.
- The `pluginName` static property has been removed. `name` is now assigned via the `BasePlugin` constructor, and is derived from the plugin name in the manifest. This means that an implementor only needs to provide a `pluginName` in the manifest, and the data is not duplicated. The value in this map (the plugin name) is used to instantiate the plugin, instead of passing static `pluginName` property into the constructor.
- CLI args are now passed in through the constructor instead of assigned to the plugin instance after the fact.
Implementation details:
`getActivePlugins()` and `getActiveDrivers()` now return a `Map` of an extension _class_ to an extension name. The key is _not_ an instance, and is effectively a singleton, so we are not at risk of a memory leak.
This change does not otherwise affect drivers.
This change modifies the type of `BasePlugin.newMethodMap`, adds a
parameter to the `MethodMap` type, and updates the base plugin TS
config for better incremental builds.