@appium/base-driver 10.7.0 → 10.7.2

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.
Files changed (159) hide show
  1. package/README.md +2 -2
  2. package/build/lib/basedriver/capabilities.d.ts +1 -1
  3. package/build/lib/basedriver/capabilities.d.ts.map +1 -1
  4. package/build/lib/basedriver/capabilities.js +4 -8
  5. package/build/lib/basedriver/capabilities.js.map +1 -1
  6. package/build/lib/basedriver/commands/bidi.d.ts.map +1 -1
  7. package/build/lib/basedriver/commands/bidi.js +1 -3
  8. package/build/lib/basedriver/commands/bidi.js.map +1 -1
  9. package/build/lib/basedriver/commands/event.d.ts.map +1 -1
  10. package/build/lib/basedriver/commands/event.js.map +1 -1
  11. package/build/lib/basedriver/commands/execute.d.ts.map +1 -1
  12. package/build/lib/basedriver/commands/execute.js +1 -1
  13. package/build/lib/basedriver/commands/execute.js.map +1 -1
  14. package/build/lib/basedriver/commands/find.d.ts.map +1 -1
  15. package/build/lib/basedriver/commands/find.js.map +1 -1
  16. package/build/lib/basedriver/commands/log.d.ts.map +1 -1
  17. package/build/lib/basedriver/commands/log.js +1 -2
  18. package/build/lib/basedriver/commands/log.js.map +1 -1
  19. package/build/lib/basedriver/commands/mixin.d.ts.map +1 -1
  20. package/build/lib/basedriver/commands/mixin.js.map +1 -1
  21. package/build/lib/basedriver/commands/timeout.d.ts.map +1 -1
  22. package/build/lib/basedriver/commands/timeout.js +1 -1
  23. package/build/lib/basedriver/commands/timeout.js.map +1 -1
  24. package/build/lib/basedriver/core.d.ts +1 -2
  25. package/build/lib/basedriver/core.d.ts.map +1 -1
  26. package/build/lib/basedriver/core.js +6 -10
  27. package/build/lib/basedriver/core.js.map +1 -1
  28. package/build/lib/basedriver/device-settings.d.ts +1 -1
  29. package/build/lib/basedriver/device-settings.d.ts.map +1 -1
  30. package/build/lib/basedriver/device-settings.js +2 -3
  31. package/build/lib/basedriver/device-settings.js.map +1 -1
  32. package/build/lib/basedriver/driver.d.ts +1 -2
  33. package/build/lib/basedriver/driver.d.ts.map +1 -1
  34. package/build/lib/basedriver/driver.js +6 -11
  35. package/build/lib/basedriver/driver.js.map +1 -1
  36. package/build/lib/basedriver/extension-core.d.ts.map +1 -1
  37. package/build/lib/basedriver/extension-core.js +1 -1
  38. package/build/lib/basedriver/extension-core.js.map +1 -1
  39. package/build/lib/basedriver/helpers.d.ts.map +1 -1
  40. package/build/lib/basedriver/helpers.js +6 -11
  41. package/build/lib/basedriver/helpers.js.map +1 -1
  42. package/build/lib/basedriver/ipc.d.ts +1 -1
  43. package/build/lib/basedriver/ipc.d.ts.map +1 -1
  44. package/build/lib/basedriver/ipc.js +3 -5
  45. package/build/lib/basedriver/ipc.js.map +1 -1
  46. package/build/lib/basedriver/validation.d.ts.map +1 -1
  47. package/build/lib/basedriver/validation.js +1 -2
  48. package/build/lib/basedriver/validation.js.map +1 -1
  49. package/build/lib/express/express-logging.d.ts.map +1 -1
  50. package/build/lib/express/express-logging.js +4 -2
  51. package/build/lib/express/express-logging.js.map +1 -1
  52. package/build/lib/express/idempotency.d.ts +1 -1
  53. package/build/lib/express/idempotency.d.ts.map +1 -1
  54. package/build/lib/express/idempotency.js +6 -9
  55. package/build/lib/express/idempotency.js.map +1 -1
  56. package/build/lib/express/middleware.d.ts +1 -1
  57. package/build/lib/express/middleware.d.ts.map +1 -1
  58. package/build/lib/express/middleware.js +1 -1
  59. package/build/lib/express/middleware.js.map +1 -1
  60. package/build/lib/express/server.d.ts +2 -2
  61. package/build/lib/express/server.d.ts.map +1 -1
  62. package/build/lib/express/server.js +8 -9
  63. package/build/lib/express/server.js.map +1 -1
  64. package/build/lib/express/websocket.d.ts.map +1 -1
  65. package/build/lib/express/websocket.js.map +1 -1
  66. package/build/lib/helpers/capabilities.d.ts +1 -1
  67. package/build/lib/helpers/capabilities.d.ts.map +1 -1
  68. package/build/lib/helpers/capabilities.js.map +1 -1
  69. package/build/lib/helpers/extension-command-name.d.ts.map +1 -1
  70. package/build/lib/helpers/extension-command-name.js.map +1 -1
  71. package/build/lib/helpers/levenshtein-match.d.ts.map +1 -1
  72. package/build/lib/helpers/levenshtein-match.js +1 -4
  73. package/build/lib/helpers/levenshtein-match.js.map +1 -1
  74. package/build/lib/index.d.ts +21 -18
  75. package/build/lib/index.d.ts.map +1 -1
  76. package/build/lib/index.js +9 -12
  77. package/build/lib/index.js.map +1 -1
  78. package/build/lib/jsonwp-proxy/protocol-converter.d.ts.map +1 -1
  79. package/build/lib/jsonwp-proxy/protocol-converter.js +6 -15
  80. package/build/lib/jsonwp-proxy/protocol-converter.js.map +1 -1
  81. package/build/lib/jsonwp-proxy/proxy.d.ts +3 -3
  82. package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
  83. package/build/lib/jsonwp-proxy/proxy.js +17 -19
  84. package/build/lib/jsonwp-proxy/proxy.js.map +1 -1
  85. package/build/lib/jsonwp-status/status.d.ts.map +1 -1
  86. package/build/lib/jsonwp-status/status.js.map +1 -1
  87. package/build/lib/protocol/errors.d.ts +1 -1
  88. package/build/lib/protocol/errors.d.ts.map +1 -1
  89. package/build/lib/protocol/errors.js +11 -28
  90. package/build/lib/protocol/errors.js.map +1 -1
  91. package/build/lib/protocol/helpers.d.ts.map +1 -1
  92. package/build/lib/protocol/helpers.js.map +1 -1
  93. package/build/lib/protocol/index.d.ts +4 -4
  94. package/build/lib/protocol/index.d.ts.map +1 -1
  95. package/build/lib/protocol/index.js +12 -12
  96. package/build/lib/protocol/index.js.map +1 -1
  97. package/build/lib/protocol/protocol.d.ts +1 -1
  98. package/build/lib/protocol/protocol.d.ts.map +1 -1
  99. package/build/lib/protocol/protocol.js +16 -30
  100. package/build/lib/protocol/protocol.js.map +1 -1
  101. package/build/lib/protocol/routes.d.ts +1 -1
  102. package/build/lib/protocol/routes.d.ts.map +1 -1
  103. package/build/lib/protocol/routes.js +5 -15
  104. package/build/lib/protocol/routes.js.map +1 -1
  105. package/build/lib/test-pages/handlers.d.ts.map +1 -1
  106. package/build/lib/test-pages/handlers.js +2 -2
  107. package/build/lib/test-pages/handlers.js.map +1 -1
  108. package/build/lib/test-pages/index.d.ts +1 -1
  109. package/build/lib/test-pages/index.d.ts.map +1 -1
  110. package/build/lib/test-pages/index.js +4 -4
  111. package/build/lib/test-pages/index.js.map +1 -1
  112. package/build/lib/test-pages/static-dir.d.ts.map +1 -1
  113. package/build/lib/test-pages/static-dir.js +5 -6
  114. package/build/lib/test-pages/static-dir.js.map +1 -1
  115. package/build/lib/test-pages/template.d.ts.map +1 -1
  116. package/build/lib/test-pages/template.js.map +1 -1
  117. package/build/lib/utils.d.ts.map +1 -1
  118. package/build/lib/utils.js.map +1 -1
  119. package/lib/basedriver/capabilities.ts +14 -37
  120. package/lib/basedriver/commands/bidi.ts +4 -14
  121. package/lib/basedriver/commands/event.ts +9 -15
  122. package/lib/basedriver/commands/execute.ts +5 -14
  123. package/lib/basedriver/commands/find.ts +3 -10
  124. package/lib/basedriver/commands/log.ts +2 -2
  125. package/lib/basedriver/commands/mixin.ts +1 -0
  126. package/lib/basedriver/commands/timeout.ts +5 -9
  127. package/lib/basedriver/core.ts +9 -15
  128. package/lib/basedriver/device-settings.ts +6 -9
  129. package/lib/basedriver/driver.ts +24 -48
  130. package/lib/basedriver/extension-core.ts +7 -12
  131. package/lib/basedriver/helpers.ts +18 -45
  132. package/lib/basedriver/ipc.ts +13 -18
  133. package/lib/basedriver/validation.ts +6 -16
  134. package/lib/express/express-logging.ts +11 -11
  135. package/lib/express/idempotency.ts +10 -19
  136. package/lib/express/middleware.ts +10 -18
  137. package/lib/express/server.ts +29 -38
  138. package/lib/express/websocket.ts +7 -13
  139. package/lib/helpers/capabilities.ts +2 -3
  140. package/lib/helpers/extension-command-name.ts +2 -4
  141. package/lib/helpers/levenshtein-match.ts +2 -7
  142. package/lib/{index.js → index.ts} +7 -9
  143. package/lib/jsonwp-proxy/protocol-converter.ts +24 -88
  144. package/lib/jsonwp-proxy/proxy.ts +34 -62
  145. package/lib/jsonwp-status/status.ts +5 -10
  146. package/lib/protocol/errors.ts +24 -70
  147. package/lib/protocol/helpers.ts +1 -0
  148. package/lib/protocol/index.ts +20 -26
  149. package/lib/protocol/protocol.ts +38 -82
  150. package/lib/protocol/routes.ts +8 -21
  151. package/lib/test-pages/handlers.ts +4 -2
  152. package/lib/test-pages/index.ts +5 -3
  153. package/lib/test-pages/static-dir.ts +6 -6
  154. package/lib/test-pages/template.ts +1 -3
  155. package/lib/utils.ts +1 -4
  156. package/package.json +29 -32
  157. package/tsconfig.json +14 -9
  158. package/LICENSE +0 -201
  159. package/index.js +0 -1
@@ -1,8 +1,9 @@
1
1
  import {console, logger, util} from '@appium/support';
2
- import morgan from 'morgan';
3
2
  import type {Request, RequestHandler, Response} from 'express';
4
- import {log} from './logger';
3
+ import morgan from 'morgan';
4
+
5
5
  import {MAX_LOG_BODY_LENGTH} from '../constants';
6
+ import {log} from './logger';
6
7
 
7
8
  /**
8
9
  * Morgan middleware that logs when the HTTP response finishes.
@@ -31,18 +32,14 @@ function startLogFormatterHandler(tokens: unknown, req: Request, res: Response):
31
32
  let reqBody = '';
32
33
  if (req.body) {
33
34
  try {
34
- reqBody = util.truncateString(
35
- typeof req.body === 'string' ? req.body : JSON.stringify(req.body),
36
- {length: MAX_LOG_BODY_LENGTH},
37
- );
35
+ reqBody = util.truncateString(typeof req.body === 'string' ? req.body : JSON.stringify(req.body), {
36
+ length: MAX_LOG_BODY_LENGTH,
37
+ });
38
38
  } catch {
39
39
  // ignore
40
40
  }
41
41
  }
42
- log.info(
43
- requestStartLoggingFormat(tokens, req, res),
44
- logger.markSensitive(console.styleText('grey', reqBody)),
45
- );
42
+ log.info(requestStartLoggingFormat(tokens, req, res), logger.markSensitive(console.styleText('grey', reqBody)));
46
43
  return undefined;
47
44
  }
48
45
 
@@ -69,7 +66,10 @@ function requestEndLoggingFormat(tokens: MorganTokens, req: Request, res: Respon
69
66
  statusStr = console.styleText('green', statusStr);
70
67
  }
71
68
  const fn = compile(
72
- `${console.styleText('white', '<-- :method :url ')}${statusStr} ${console.styleText('grey', ':response-time ms - :res[content-length]')}`,
69
+ `${console.styleText('white', '<-- :method :url ')}${statusStr} ${console.styleText(
70
+ 'grey',
71
+ ':response-time ms - :res[content-length]',
72
+ )}`,
73
73
  );
74
74
  return fn(tokens, req, res);
75
75
  }
@@ -1,8 +1,10 @@
1
- import {log} from './logger';
2
- import {LRUCache} from 'lru-cache';
3
- import {util} from '@appium/support';
4
1
  import {EventEmitter} from 'node:events';
5
- import type {Request, Response, NextFunction} from 'express';
2
+
3
+ import {util} from '@appium/support';
4
+ import type {NextFunction, Request, Response} from 'express';
5
+ import {LRUCache} from 'lru-cache';
6
+
7
+ import {log} from './logger';
6
8
 
7
9
  interface CachedResponse {
8
10
  method: string;
@@ -28,11 +30,7 @@ const MAX_CACHED_PAYLOAD_SIZE_BYTES = 1 * 1024 * 1024; // 1 MiB
28
30
  * Middleware that caches and replays responses for idempotent requests using the
29
31
  * `x-idempotency-key` header. Only POST and PATCH are cached.
30
32
  */
31
- export async function handleIdempotency(
32
- req: Request,
33
- res: Response,
34
- next: NextFunction,
35
- ): Promise<void> {
33
+ export async function handleIdempotency(req: Request, res: Response, next: NextFunction): Promise<void> {
36
34
  const keyOrArr = req.headers[IDEMPOTENCY_KEY_HEADER];
37
35
  if (util.isEmpty(keyOrArr) || !keyOrArr) {
38
36
  next();
@@ -133,8 +131,7 @@ function cacheResponse(key: string, req: Request, res: Response): void {
133
131
  responseSize += buf.length;
134
132
  if (responseSize > MAX_CACHED_PAYLOAD_SIZE_BYTES) {
135
133
  errorMessage =
136
- `The actual response size exceeds ` +
137
- `the maximum allowed limit of ${MAX_CACHED_PAYLOAD_SIZE_BYTES} bytes`;
134
+ `The actual response size exceeds ` + `the maximum allowed limit of ${MAX_CACHED_PAYLOAD_SIZE_BYTES} bytes`;
138
135
  }
139
136
  return originalSocketWriter(
140
137
  chunk as string | Buffer | Uint8Array,
@@ -151,10 +148,7 @@ function cacheResponse(key: string, req: Request, res: Response): void {
151
148
  }
152
149
 
153
150
  if (!IDEMPOTENT_RESPONSES.has(key)) {
154
- log.info(
155
- `Could not cache the response identified by '${key}'. ` +
156
- `Cache consistency has been damaged`,
157
- );
151
+ log.info(`Could not cache the response identified by '${key}'. ` + `Cache consistency has been damaged`);
158
152
  } else {
159
153
  log.info(`Could not cache the response identified by '${key}': ${errorMessage}`);
160
154
  IDEMPOTENT_RESPONSES.delete(key);
@@ -173,10 +167,7 @@ function cacheResponse(key: string, req: Request, res: Response): void {
173
167
  }
174
168
 
175
169
  if (!IDEMPOTENT_RESPONSES.has(key)) {
176
- log.info(
177
- `Could not cache the response identified by '${key}'. ` +
178
- `Cache consistency has been damaged`,
179
- );
170
+ log.info(`Could not cache the response identified by '${key}'. ` + `Cache consistency has been damaged`);
180
171
  } else if (errorMessage) {
181
172
  log.info(`Could not cache the response identified by '${key}': ${errorMessage}`);
182
173
  IDEMPOTENT_RESPONSES.delete(key);
@@ -1,14 +1,17 @@
1
- import {util} from '@appium/support';
2
- import type {NextFunction, Request, RequestHandler, Response} from 'express';
3
1
  import type {IncomingMessage} from 'node:http';
4
2
  import type {Duplex} from 'node:stream';
5
- import {log} from './logger';
3
+
4
+ import {util} from '@appium/support';
5
+ import type {NextFunction, Request, RequestHandler, Response} from 'express';
6
+
6
7
  import {errors} from '../protocol';
8
+ import {log} from './logger';
7
9
  export {handleIdempotency} from './idempotency';
10
+ import type {StringRecord, WSServer} from '@appium/types';
8
11
  import {match} from 'path-to-regexp';
12
+
9
13
  import {calcSignature} from '../helpers/session';
10
14
  import {getResponseForW3CError} from '../protocol/errors';
11
- import type {StringRecord, WSServer} from '@appium/types';
12
15
 
13
16
  const SESSION_ID_PATTERN = /\/session\/([^/]+)/;
14
17
 
@@ -39,11 +42,7 @@ export function allowCrossDomain(req: Request, res: Response, next: NextFunction
39
42
  * @returns Express request handler
40
43
  */
41
44
  export function allowCrossDomainAsyncExecute(basePath: string): RequestHandler {
42
- function allowCrossDomainAsyncExecuteHandler(
43
- req: Request,
44
- res: Response,
45
- next: NextFunction,
46
- ): void {
45
+ function allowCrossDomainAsyncExecuteHandler(req: Request, res: Response, next: NextFunction): void {
47
46
  const receiveAsyncResponseRegExp = new RegExp(
48
47
  `${util.escapeRegExp(basePath)}/session/[a-f0-9-]+/(appium/)?receive_async_response`,
49
48
  );
@@ -72,9 +71,7 @@ export function handleLogContext(req: Request, _res: Response, next: NextFunctio
72
71
  {
73
72
  requestId,
74
73
  ...sessionInfo,
75
- isSensitive: ['true', '1', 'yes'].includes(
76
- String(isSensitiveHeaderValue ?? '').toLowerCase(),
77
- ),
74
+ isSensitive: ['true', '1', 'yes'].includes(String(isSensitiveHeaderValue ?? '').toLowerCase()),
78
75
  },
79
76
  true,
80
77
  );
@@ -151,12 +148,7 @@ export function handleUpgrade(webSocketsMapping: StringRecord<WSServer>): Reques
151
148
  * Final error-handling middleware.
152
149
  * Logs uncaught errors and returns a W3C-formatted error response unless headers were already sent.
153
150
  */
154
- export function catchAllHandler(
155
- err: Error,
156
- _req: Request,
157
- res: Response,
158
- next: NextFunction,
159
- ): void {
151
+ export function catchAllHandler(err: Error, _req: Request, res: Response, next: NextFunction): void {
160
152
  if (res.headersSent) {
161
153
  next(err);
162
154
  return;
@@ -1,42 +1,44 @@
1
- import express from 'express';
2
- import type {Express, RequestHandler} from 'express';
3
1
  import http from 'node:http';
4
2
  import type {Server as HttpServer} from 'node:http';
5
3
  import {createRequire} from 'node:module';
4
+
5
+ // Import env helper directly — not from the test-pages barrel — so Express handlers and
6
+ // fixture code stay unloaded unless APPIUM_ENABLE_LEGACY_TEST_PAGES is set.
7
+ import {fs, timing} from '@appium/support';
8
+ import type {
9
+ AppiumServer,
10
+ ExternalDriver,
11
+ MethodMap,
12
+ ServerArgs,
13
+ StringRecord,
14
+ UpdateServerCallback,
15
+ } from '@appium/types';
6
16
  import bodyParser from 'body-parser';
17
+ import express from 'express';
18
+ import type {Express, RequestHandler} from 'express';
7
19
  import methodOverride from 'method-override';
20
+
21
+ import {DEFAULT_BASE_PATH} from '../constants';
22
+ import {isLegacyTestPagesEnabled} from '../test-pages/env';
23
+ import {endLogFormatter, startLogFormatter} from './express-logging';
8
24
  import {log} from './logger';
9
- import {startLogFormatter, endLogFormatter} from './express-logging';
10
25
  import {
11
26
  allowCrossDomain,
12
- defaultToJSONContentType,
13
- catchAllHandler,
14
27
  allowCrossDomainAsyncExecute,
28
+ catch404Handler,
29
+ catchAllHandler,
30
+ defaultToJSONContentType,
15
31
  handleIdempotency,
32
+ handleLogContext,
16
33
  handleUpgrade,
17
34
  tryHandleWebSocketUpgrade,
18
- catch404Handler,
19
- handleLogContext,
20
35
  } from './middleware';
21
- // Import env helper directly — not from the test-pages barrel — so Express handlers and
22
- // fixture code stay unloaded unless APPIUM_ENABLE_LEGACY_TEST_PAGES is set.
23
- import {isLegacyTestPagesEnabled} from '../test-pages/env';
24
36
  import {
25
37
  addWebSocketHandler,
26
- removeWebSocketHandler,
27
- removeAllWebSocketHandlers,
28
38
  getWebSocketHandlers,
39
+ removeAllWebSocketHandlers,
40
+ removeWebSocketHandler,
29
41
  } from './websocket';
30
- import {DEFAULT_BASE_PATH} from '../constants';
31
- import {fs, timing} from '@appium/support';
32
- import type {
33
- AppiumServer,
34
- ServerArgs,
35
- UpdateServerCallback,
36
- MethodMap,
37
- ExternalDriver,
38
- StringRecord,
39
- } from '@appium/types';
40
42
 
41
43
  const KEEP_ALIVE_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
42
44
 
@@ -265,10 +267,7 @@ async function createServer(app: Express, cliArgs?: Partial<ServerArgs>): Promis
265
267
  throw new Error(`The provided SSL ${desc} at '${p}' does not exist or is not accessible`);
266
268
  }
267
269
  }
268
- const [cert, key] = (await Promise.all(certKey.map((p) => fs.readFile(p, 'utf8')))) as [
269
- string,
270
- string,
271
- ];
270
+ const [cert, key] = (await Promise.all(certKey.map((p) => fs.readFile(p, 'utf8')))) as [string, string];
272
271
  log.debug('Enabling TLS/SPDY on the server using the provided certificate');
273
272
 
274
273
  const spdy = require('spdy') as {
@@ -320,8 +319,7 @@ function configureHttp({
320
319
  // shouldUpgradeCallback only returns a boolean to indicate if the upgrade should proceed
321
320
  (
322
321
  appiumServer as unknown as {shouldUpgradeCallback?: (req: http.IncomingMessage) => boolean}
323
- ).shouldUpgradeCallback = (req) =>
324
- String(req.headers?.upgrade ?? '').toLowerCase() === 'websocket';
322
+ ).shouldUpgradeCallback = (req) => String(req.headers?.upgrade ?? '').toLowerCase() === 'websocket';
325
323
  appiumServer.on('upgrade', (req, socket, head) => {
326
324
  if (!tryHandleWebSocketUpgrade(req, socket, head, appiumServer.webSocketsMapping)) {
327
325
  socket.destroy();
@@ -331,9 +329,7 @@ function configureHttp({
331
329
 
332
330
  // http.Server.close() only stops new connections, but we need to wait until
333
331
  // all connections are closed and the `close` event is emitted
334
- const originalClose = appiumServer.close.bind(appiumServer) as (
335
- callback?: (err?: Error | null) => void,
336
- ) => void;
332
+ const originalClose = appiumServer.close.bind(appiumServer) as (callback?: (err?: Error | null) => void) => void;
337
333
  appiumServer.close = async () =>
338
334
  await new Promise<void>((_resolve, _reject) => {
339
335
  log.info('Closing Appium HTTP server');
@@ -368,9 +364,7 @@ function configureHttp({
368
364
 
369
365
  appiumServer.once('error', (err: NodeJS.ErrnoException) => {
370
366
  if (err.code === 'EADDRNOTAVAIL') {
371
- log.error(
372
- 'Could not start REST http interface listener. ' + 'Requested address is not available.',
373
- );
367
+ log.error('Could not start REST http interface listener. ' + 'Requested address is not available.');
374
368
  } else {
375
369
  log.error(
376
370
  'Could not start REST http interface listener. The requested ' +
@@ -426,10 +420,7 @@ function hasShouldUpgradeCallback(server: HttpServer): boolean {
426
420
  // Check if shouldUpgradeCallback is available on http.Server
427
421
  // This is a runtime check that works regardless of TypeScript types
428
422
  try {
429
- return (
430
- typeof (server as unknown as {shouldUpgradeCallback?: unknown}).shouldUpgradeCallback !==
431
- 'undefined'
432
- );
423
+ return typeof (server as unknown as {shouldUpgradeCallback?: unknown}).shouldUpgradeCallback !== 'undefined';
433
424
  } catch {
434
425
  return false;
435
426
  }
@@ -23,25 +23,19 @@ export async function getWebSocketHandlers(
23
23
  this: AppiumServer,
24
24
  keysFilter: string | null = null,
25
25
  ): Promise<Record<string, WSServer>> {
26
- return Object.entries(this.webSocketsMapping).reduce<Record<string, WSServer>>(
27
- (acc, [pathname, wsServer]) => {
28
- if (typeof keysFilter !== 'string' || pathname.includes(keysFilter)) {
29
- acc[pathname] = wsServer;
30
- }
31
- return acc;
32
- },
33
- {},
34
- );
26
+ return Object.entries(this.webSocketsMapping).reduce<Record<string, WSServer>>((acc, [pathname, wsServer]) => {
27
+ if (typeof keysFilter !== 'string' || pathname.includes(keysFilter)) {
28
+ acc[pathname] = wsServer;
29
+ }
30
+ return acc;
31
+ }, {});
35
32
  }
36
33
 
37
34
  /**
38
35
  * Removes a WebSocket handler by pathname.
39
36
  * @see AppiumServerExtension.removeWebSocketHandler
40
37
  */
41
- export async function removeWebSocketHandler(
42
- this: AppiumServer,
43
- handlerPathname: string,
44
- ): Promise<boolean> {
38
+ export async function removeWebSocketHandler(this: AppiumServer, handlerPathname: string): Promise<boolean> {
45
39
  const wsServer = this.webSocketsMapping?.[handlerPathname];
46
40
  if (!wsServer) {
47
41
  return false;
@@ -1,5 +1,5 @@
1
- import type {Constraints, W3CCapabilities, Capabilities, AppiumLogger} from '@appium/types';
2
1
  import {util} from '@appium/support';
2
+ import type {AppiumLogger, Capabilities, Constraints, W3CCapabilities} from '@appium/types';
3
3
 
4
4
  /**
5
5
  * Determine whether the given argument is valid
@@ -38,8 +38,7 @@ export function fixCaps<C extends Constraints>(
38
38
  ): Capabilities<C> {
39
39
  const caps = {...oldCaps} as Record<string, unknown>;
40
40
 
41
- const logCastWarning = (prefix: string) =>
42
- log.warn(`${prefix}. This may cause unexpected behavior`);
41
+ const logCastWarning = (prefix: string) => log.warn(`${prefix}. This may cause unexpected behavior`);
43
42
 
44
43
  // boolean capabilities can be passed in as strings 'false' and 'true'
45
44
  // which we want to translate into boolean values
@@ -1,5 +1,6 @@
1
1
  import {util} from '@appium/support';
2
2
  import type {Constraints, Driver, DriverClass} from '@appium/types';
3
+
3
4
  import type {BaseDriver} from '../basedriver/driver';
4
5
 
5
6
  /**
@@ -9,10 +10,7 @@ import type {BaseDriver} from '../basedriver/driver';
9
10
  * @param commandName - The command name to resolve.
10
11
  * @returns The resolved extension command name if a mapping exists. Otherwise, the original command name.
11
12
  */
12
- export function resolveExecuteExtensionName<C extends Constraints>(
13
- this: BaseDriver<C>,
14
- commandName: string,
15
- ): string {
13
+ export function resolveExecuteExtensionName<C extends Constraints>(this: BaseDriver<C>, commandName: string): string {
16
14
  const Driver = this.constructor as DriverClass<Driver<C>>;
17
15
  const methodMap = Driver.executeMethodMap;
18
16
 
@@ -41,19 +41,14 @@ export function rankLevenshteinCandidates(
41
41
  },
42
42
  {} as StringRecord<string[]>,
43
43
  );
44
- const sortedDistanceKeys = Object.keys(matchesMap).sort(
45
- (a, b) => parseInt(a, 10) - parseInt(b, 10),
46
- );
44
+ const sortedDistanceKeys = Object.keys(matchesMap).sort((a, b) => parseInt(a, 10) - parseInt(b, 10));
47
45
  const sorted = sortedDistanceKeys.flatMap((k) => (matchesMap[k] ?? []).sort());
48
46
 
49
47
  const best = sorted[0];
50
48
  const firstDistanceKey = sortedDistanceKeys[0];
51
49
  const minDist = firstDistanceKey !== undefined ? parseInt(firstDistanceKey, 10) : NaN;
52
50
  const suggestion =
53
- maxEditDistance >= 0 &&
54
- best !== undefined &&
55
- !Number.isNaN(minDist) &&
56
- minDist <= maxEditDistance
51
+ maxEditDistance >= 0 && best !== undefined && !Number.isNaN(minDist) && minDist <= maxEditDistance
57
52
  ? best
58
53
  : undefined;
59
54
  return {sorted, suggestion};
@@ -7,7 +7,7 @@ export {AppiumIpc} from './basedriver/ipc';
7
7
 
8
8
  export {BaseDriver};
9
9
  export default BaseDriver;
10
- export {MAX_LOG_BODY_LENGTH, DEFAULT_BASE_PATH, PROTOCOLS, W3C_ELEMENT_KEY} from './constants';
10
+ export {DEFAULT_BASE_PATH, MAX_LOG_BODY_LENGTH, PROTOCOLS, W3C_ELEMENT_KEY} from './constants';
11
11
 
12
12
  // MJSONWP exports
13
13
  export * from './protocol';
@@ -15,8 +15,8 @@ export {errorFromMJSONWPStatusCode as errorFromCode} from './protocol';
15
15
 
16
16
  // Express exports
17
17
  /** @deprecated Removed in Appium 4. Use hard-copied test fixtures in driver CI instead. */
18
+ export {normalizeBasePath, server} from './express/server';
18
19
  export {TEST_FIXTURES_DIR as STATIC_DIR} from './test-pages';
19
- export {server, normalizeBasePath} from './express/server';
20
20
 
21
21
  // jsonwp-proxy exports
22
22
  /** @deprecated The JWProxy export is deprecated. Please use WebDriverProxy instead */
@@ -24,17 +24,17 @@ export {JWProxy} from './jsonwp-proxy/proxy';
24
24
  export {JWProxy as WebDriverProxy} from './jsonwp-proxy/proxy';
25
25
 
26
26
  // jsonwp-status exports
27
- export {getSummaryByCode, codes as statusCodes} from './jsonwp-status/status';
27
+ export {codes as statusCodes, getSummaryByCode} from './jsonwp-status/status';
28
28
 
29
29
  // W3C capabilities parser
30
30
  export {
31
+ isStandardCap,
31
32
  PREFIXED_APPIUM_OPTS_CAP,
32
- STANDARD_CAPS,
33
33
  processCapabilities,
34
- isStandardCap,
35
- validateCaps,
36
34
  promoteAppiumOptions,
37
35
  promoteAppiumOptionsForObject,
36
+ STANDARD_CAPS,
37
+ validateCaps,
38
38
  } from './basedriver/capabilities';
39
39
 
40
40
  // Web socket helpers
@@ -47,6 +47,4 @@ export {generateDriverLogPrefix} from './basedriver/helpers';
47
47
 
48
48
  export {isW3cCaps} from './helpers/capabilities';
49
49
 
50
- /**
51
- * @typedef {import('./express/server').ServerOpts} ServerOpts
52
- */
50
+ export type {ServerOpts} from './express/server';
@@ -1,26 +1,21 @@
1
- import type {AppiumLogger, HTTPBody, ProxyResponse} from '@appium/types';
2
1
  import {logger, util} from '@appium/support';
2
+ import type {AppiumLogger, HTTPBody, ProxyResponse} from '@appium/types';
3
+
3
4
  import {duplicateKeys} from '../basedriver/helpers';
4
- import {MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY, PROTOCOLS} from '../constants';
5
+ import {MJSONWP_ELEMENT_KEY, PROTOCOLS, W3C_ELEMENT_KEY} from '../constants';
5
6
 
6
- export type ProxyFunction = (
7
- url: string,
8
- method: string,
9
- body?: HTTPBody,
10
- ) => Promise<[ProxyResponse, HTTPBody]>;
7
+ export type ProxyFunction = (url: string, method: string, body?: HTTPBody) => Promise<[ProxyResponse, HTTPBody]>;
11
8
 
12
9
  export const COMMAND_URLS_CONFLICTS = [
13
10
  {
14
11
  commandNames: ['execute', 'executeAsync'],
15
- jsonwpConverter: (url: string) =>
16
- url.replace(/\/execute.*/, url.includes('async') ? '/execute_async' : '/execute'),
12
+ jsonwpConverter: (url: string) => url.replace(/\/execute.*/, url.includes('async') ? '/execute_async' : '/execute'),
17
13
  w3cConverter: (url: string) =>
18
14
  url.replace(/\/execute.*/, url.includes('async') ? '/execute/async' : '/execute/sync'),
19
15
  },
20
16
  {
21
17
  commandNames: ['getElementScreenshot'],
22
- jsonwpConverter: (url: string) =>
23
- url.replace(/\/element\/([^/]+)\/screenshot$/, '/screenshot/$1'),
18
+ jsonwpConverter: (url: string) => url.replace(/\/element\/([^/]+)\/screenshot$/, '/screenshot/$1'),
24
19
  w3cConverter: (url: string) => url.replace(/\/screenshot\/([^/]+)/, '/element/$1/screenshot'),
25
20
  },
26
21
  {
@@ -114,17 +109,12 @@ export class ProtocolConverter {
114
109
  if (!(commandNames as readonly string[]).includes(commandName)) {
115
110
  continue;
116
111
  }
117
- const rewrittenUrl =
118
- this.downstreamProtocol === MJSONWP ? jsonwpConverter(url) : w3cConverter(url);
112
+ const rewrittenUrl = this.downstreamProtocol === MJSONWP ? jsonwpConverter(url) : w3cConverter(url);
119
113
  if (rewrittenUrl === url) {
120
- this.log.debug(
121
- `Did not know how to rewrite the original URL '${url}' for ${this.downstreamProtocol} protocol`,
122
- );
114
+ this.log.debug(`Did not know how to rewrite the original URL '${url}' for ${this.downstreamProtocol} protocol`);
123
115
  break;
124
116
  }
125
- this.log.info(
126
- `Rewrote the original URL '${url}' to '${rewrittenUrl}' for ${this.downstreamProtocol} protocol`,
127
- );
117
+ this.log.info(`Rewrote the original URL '${url}' to '${rewrittenUrl}' for ${this.downstreamProtocol} protocol`);
128
118
  return await this.proxyFunc(rewrittenUrl, method, body);
129
119
  }
130
120
 
@@ -143,11 +133,7 @@ export class ProtocolConverter {
143
133
  }
144
134
 
145
135
  const bodyObj = (util.safeJsonParse(body) as Record<string, unknown>) ?? {};
146
- if (
147
- this.downstreamProtocol === W3C &&
148
- Object.hasOwn(bodyObj, 'ms') &&
149
- Object.hasOwn(bodyObj, 'type')
150
- ) {
136
+ if (this.downstreamProtocol === W3C && Object.hasOwn(bodyObj, 'ms') && Object.hasOwn(bodyObj, 'type')) {
151
137
  const typeToW3C = (x: string) => (x === 'page load' ? 'pageLoad' : x);
152
138
  return [
153
139
  {
@@ -156,10 +142,7 @@ export class ProtocolConverter {
156
142
  ];
157
143
  }
158
144
 
159
- if (
160
- this.downstreamProtocol === MJSONWP &&
161
- (!Object.hasOwn(bodyObj, 'ms') || !Object.hasOwn(bodyObj, 'type'))
162
- ) {
145
+ if (this.downstreamProtocol === MJSONWP && (!Object.hasOwn(bodyObj, 'ms') || !Object.hasOwn(bodyObj, 'type'))) {
163
146
  const typeToJSONWP = (x: string) => (x === 'pageLoad' ? 'page load' : x);
164
147
  return (
165
148
  Object.entries(bodyObj)
@@ -178,18 +161,12 @@ export class ProtocolConverter {
178
161
  /**
179
162
  * Proxy an array of timeout objects and merge the result.
180
163
  */
181
- private async proxySetTimeouts(
182
- url: string,
183
- method: string,
184
- body?: HTTPBody,
185
- ): Promise<[ProxyResponse, HTTPBody]> {
164
+ private async proxySetTimeouts(url: string, method: string, body?: HTTPBody): Promise<[ProxyResponse, HTTPBody]> {
186
165
  const timeoutRequestObjects = this.getTimeoutRequestObjects(body);
187
166
  if (timeoutRequestObjects.length === 0) {
188
167
  return await this.proxyFunc(url, method, body);
189
168
  }
190
- this.log.debug(
191
- `Will send the following request bodies to /timeouts: ${JSON.stringify(timeoutRequestObjects)}`,
192
- );
169
+ this.log.debug(`Will send the following request bodies to /timeouts: ${JSON.stringify(timeoutRequestObjects)}`);
193
170
 
194
171
  let response!: ProxyResponse;
195
172
  let resBody!: HTTPBody;
@@ -209,27 +186,15 @@ export class ProtocolConverter {
209
186
  return [response, resBody];
210
187
  }
211
188
 
212
- private async proxySetWindow(
213
- url: string,
214
- method: string,
215
- body: HTTPBody,
216
- ): Promise<[ProxyResponse, HTTPBody]> {
189
+ private async proxySetWindow(url: string, method: string, body: HTTPBody): Promise<[ProxyResponse, HTTPBody]> {
217
190
  const bodyObj = util.safeJsonParse(body);
218
191
  if (util.isPlainObject(bodyObj)) {
219
192
  const obj = bodyObj as Record<string, unknown>;
220
- if (
221
- this.downstreamProtocol === W3C &&
222
- Object.hasOwn(bodyObj, 'name') &&
223
- !Object.hasOwn(bodyObj, 'handle')
224
- ) {
193
+ if (this.downstreamProtocol === W3C && Object.hasOwn(bodyObj, 'name') && !Object.hasOwn(bodyObj, 'handle')) {
225
194
  this.log.debug(`Copied 'name' value '${obj.name}' to 'handle' as per W3C spec`);
226
195
  return await this.proxyFunc(url, method, {...obj, handle: obj.name});
227
196
  }
228
- if (
229
- this.downstreamProtocol === MJSONWP &&
230
- Object.hasOwn(bodyObj, 'handle') &&
231
- !Object.hasOwn(bodyObj, 'name')
232
- ) {
197
+ if (this.downstreamProtocol === MJSONWP && Object.hasOwn(bodyObj, 'handle') && !Object.hasOwn(bodyObj, 'name')) {
233
198
  this.log.debug(`Copied 'handle' value '${obj.handle}' to 'name' as per JSONWP spec`);
234
199
  return await this.proxyFunc(url, method, {...obj, name: obj.handle});
235
200
  }
@@ -237,16 +202,9 @@ export class ProtocolConverter {
237
202
  return await this.proxyFunc(url, method, body);
238
203
  }
239
204
 
240
- private async proxySetValue(
241
- url: string,
242
- method: string,
243
- body: HTTPBody,
244
- ): Promise<[ProxyResponse, HTTPBody]> {
205
+ private async proxySetValue(url: string, method: string, body: HTTPBody): Promise<[ProxyResponse, HTTPBody]> {
245
206
  const bodyObj = util.safeJsonParse(body) as Record<string, unknown> | undefined;
246
- if (
247
- util.isPlainObject(bodyObj) &&
248
- (util.hasValue(bodyObj?.text) || util.hasValue(bodyObj?.value))
249
- ) {
207
+ if (util.isPlainObject(bodyObj) && (util.hasValue(bodyObj?.text) || util.hasValue(bodyObj?.value))) {
250
208
  let {text, value} = bodyObj;
251
209
  if (util.hasValue(text) && !util.hasValue(value)) {
252
210
  value = typeof text === 'string' ? [...text] : Array.isArray(text) ? text : [];
@@ -260,48 +218,26 @@ export class ProtocolConverter {
260
218
  return await this.proxyFunc(url, method, body);
261
219
  }
262
220
 
263
- private async proxySetFrame(
264
- url: string,
265
- method: string,
266
- body: HTTPBody,
267
- ): Promise<[ProxyResponse, HTTPBody]> {
221
+ private async proxySetFrame(url: string, method: string, body: HTTPBody): Promise<[ProxyResponse, HTTPBody]> {
268
222
  const bodyObj = util.safeJsonParse(body);
269
- if (
270
- Object.hasOwn(bodyObj ?? {}, 'id') &&
271
- util.isPlainObject((bodyObj as Record<string, unknown>).id)
272
- ) {
223
+ if (Object.hasOwn(bodyObj ?? {}, 'id') && util.isPlainObject((bodyObj as Record<string, unknown>).id)) {
273
224
  return await this.proxyFunc(url, method, {
274
225
  ...(bodyObj as object),
275
- id: duplicateKeys(
276
- (bodyObj as Record<string, unknown>).id as object,
277
- MJSONWP_ELEMENT_KEY,
278
- W3C_ELEMENT_KEY,
279
- ),
226
+ id: duplicateKeys((bodyObj as Record<string, unknown>).id as object, MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY),
280
227
  });
281
228
  }
282
229
  return await this.proxyFunc(url, method, body);
283
230
  }
284
231
 
285
- private async proxyPerformActions(
286
- url: string,
287
- method: string,
288
- body: HTTPBody,
289
- ): Promise<[ProxyResponse, HTTPBody]> {
232
+ private async proxyPerformActions(url: string, method: string, body: HTTPBody): Promise<[ProxyResponse, HTTPBody]> {
290
233
  const bodyObj = util.safeJsonParse(body);
291
234
  if (util.isPlainObject(bodyObj)) {
292
- return await this.proxyFunc(
293
- url,
294
- method,
295
- duplicateKeys(bodyObj as object, MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY),
296
- );
235
+ return await this.proxyFunc(url, method, duplicateKeys(bodyObj as object, MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY));
297
236
  }
298
237
  return await this.proxyFunc(url, method, body);
299
238
  }
300
239
 
301
- private async proxyReleaseActions(
302
- url: string,
303
- method: string,
304
- ): Promise<[ProxyResponse, HTTPBody]> {
240
+ private async proxyReleaseActions(url: string, method: string): Promise<[ProxyResponse, HTTPBody]> {
305
241
  return await this.proxyFunc(url, method);
306
242
  }
307
243
  }