browser-debugger-cli 0.8.0 → 0.9.0

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 (251) hide show
  1. package/README.md +4 -1
  2. package/dist/cdp/schema.d.ts +4 -1
  3. package/dist/cdp/schema.js +48 -7
  4. package/dist/commands/cdp.js +3 -2
  5. package/dist/commands/cleanup.d.ts +11 -0
  6. package/dist/commands/cleanup.js +161 -57
  7. package/dist/commands/console.d.ts +20 -1
  8. package/dist/commands/console.js +57 -17
  9. package/dist/commands/details.js +3 -2
  10. package/dist/commands/dom/DomElementResolver.d.ts +10 -3
  11. package/dist/commands/dom/DomElementResolver.js +35 -17
  12. package/dist/commands/dom/a11y.d.ts +10 -0
  13. package/dist/commands/dom/a11y.js +27 -5
  14. package/dist/commands/dom/eval.d.ts +3 -1
  15. package/dist/commands/dom/eval.js +29 -4
  16. package/dist/commands/dom/form.js +16 -62
  17. package/dist/commands/dom/formInteraction.js +152 -113
  18. package/dist/commands/dom/formSummary.d.ts +49 -0
  19. package/dist/commands/dom/formSummary.js +180 -0
  20. package/dist/commands/dom/frames.d.ts +2 -1
  21. package/dist/commands/dom/frames.js +17 -2
  22. package/dist/commands/dom/get.d.ts +6 -5
  23. package/dist/commands/dom/get.js +92 -82
  24. package/dist/commands/dom/helpers/index.d.ts +1 -1
  25. package/dist/commands/dom/helpers/index.js +1 -1
  26. package/dist/commands/dom/helpers/query.d.ts +44 -17
  27. package/dist/commands/dom/helpers/query.js +244 -97
  28. package/dist/commands/dom/helpers/runElementCommand.d.ts +10 -2
  29. package/dist/commands/dom/helpers/runElementCommand.js +97 -30
  30. package/dist/commands/dom/helpers/screenshot.d.ts +4 -1
  31. package/dist/commands/dom/helpers/screenshot.js +164 -49
  32. package/dist/commands/dom/index.d.ts +3 -1
  33. package/dist/commands/dom/index.js +16 -6
  34. package/dist/commands/dom/layout.d.ts +14 -0
  35. package/dist/commands/dom/layout.js +54 -0
  36. package/dist/commands/dom/listeners.d.ts +5 -1
  37. package/dist/commands/dom/listeners.js +13 -3
  38. package/dist/commands/dom/query.js +2 -3
  39. package/dist/commands/dom/screenshot.d.ts +12 -2
  40. package/dist/commands/dom/screenshot.js +27 -3
  41. package/dist/commands/dom/semanticUtils.d.ts +6 -13
  42. package/dist/commands/dom/semanticUtils.js +15 -19
  43. package/dist/commands/dom/wait.d.ts +13 -0
  44. package/dist/commands/dom/wait.js +83 -0
  45. package/dist/commands/helpJson.js +2 -2
  46. package/dist/commands/network/list.js +4 -11
  47. package/dist/commands/optionBehaviors.js +112 -21
  48. package/dist/commands/page.d.ts +2 -1
  49. package/dist/commands/page.js +41 -5
  50. package/dist/commands/peek.js +4 -11
  51. package/dist/commands/sessions.d.ts +8 -0
  52. package/dist/commands/sessions.js +19 -0
  53. package/dist/commands/shared/CommandRunner.js +4 -4
  54. package/dist/commands/shared/dataFetcher.js +2 -2
  55. package/dist/commands/shared/followMode.d.ts +21 -1
  56. package/dist/commands/shared/followMode.js +29 -2
  57. package/dist/commands/shared/handleValidationError.d.ts +2 -2
  58. package/dist/commands/shared/handleValidationError.js +12 -3
  59. package/dist/commands/shared/optionTypes.d.ts +40 -5
  60. package/dist/commands/shared/startHelpers.js +12 -3
  61. package/dist/commands/shared/validation.d.ts +3 -2
  62. package/dist/commands/shared/validation.js +4 -3
  63. package/dist/commands/start.d.ts +63 -0
  64. package/dist/commands/start.js +115 -15
  65. package/dist/commands/status.js +29 -7
  66. package/dist/commands/stop.js +7 -6
  67. package/dist/commands/tail.js +4 -11
  68. package/dist/commands/types.d.ts +2 -0
  69. package/dist/commands.js +2 -0
  70. package/dist/connection/chromeIdentity.d.ts +65 -0
  71. package/dist/connection/chromeIdentity.js +143 -0
  72. package/dist/connection/launcher/profilePreferences.d.ts +47 -0
  73. package/dist/connection/launcher/profilePreferences.js +151 -0
  74. package/dist/connection/launcher.d.ts +21 -2
  75. package/dist/connection/launcher.js +42 -16
  76. package/dist/connection/portReservation.d.ts +14 -4
  77. package/dist/connection/portReservation.js +21 -6
  78. package/dist/connection/startupExit.d.ts +8 -0
  79. package/dist/connection/startupExit.js +15 -6
  80. package/dist/constants.d.ts +6 -2
  81. package/dist/constants.js +9 -2
  82. package/dist/daemon/SessionController.js +23 -7
  83. package/dist/daemon/errors.d.ts +1 -1
  84. package/dist/daemon/errors.js +1 -1
  85. package/dist/daemon/launcher.d.ts +2 -1
  86. package/dist/daemon/launcher.js +5 -6
  87. package/dist/daemon/server/SocketServer.js +1 -2
  88. package/dist/daemon/session/Session.d.ts +13 -0
  89. package/dist/daemon/session/Session.js +57 -8
  90. package/dist/daemon/session/chromeConnection.d.ts +9 -0
  91. package/dist/daemon/session/chromeConnection.js +45 -8
  92. package/dist/daemon/session/commandRegistry.js +52 -62
  93. package/dist/daemon/session/interactions.d.ts +35 -9
  94. package/dist/daemon/session/interactions.js +36 -9
  95. package/dist/daemon/session/triggeredRequests.d.ts +67 -0
  96. package/dist/daemon/session/triggeredRequests.js +157 -0
  97. package/dist/daemon/session/types.d.ts +5 -1
  98. package/dist/daemon.js +5393 -1600
  99. package/dist/errors/messages.d.ts +387 -24
  100. package/dist/errors/messages.js +761 -67
  101. package/dist/index.js +3976 -1558
  102. package/dist/ipc/client.d.ts +12 -1
  103. package/dist/ipc/client.js +22 -3
  104. package/dist/ipc/protocol/commands.d.ts +89 -4
  105. package/dist/ipc/protocol/commands.js +2 -0
  106. package/dist/ipc/protocol/domTypes.d.ts +258 -7
  107. package/dist/ipc/session/lifecycle.d.ts +8 -1
  108. package/dist/ipc/session/queries.d.ts +5 -1
  109. package/dist/ipc/session/types.d.ts +5 -0
  110. package/dist/ipc/transport/index.d.ts +2 -1
  111. package/dist/ipc/transport/index.js +2 -2
  112. package/dist/runtime/dom/actionEffects.d.ts +106 -0
  113. package/dist/runtime/dom/actionEffects.js +256 -0
  114. package/dist/runtime/dom/actionEffectsScripts.d.ts +52 -0
  115. package/dist/runtime/dom/actionEffectsScripts.js +234 -0
  116. package/dist/runtime/dom/elementGeometry.d.ts +170 -0
  117. package/dist/runtime/dom/elementGeometry.js +553 -0
  118. package/dist/runtime/dom/elementInfo.d.ts +77 -0
  119. package/dist/runtime/dom/elementInfo.js +191 -0
  120. package/dist/runtime/dom/evalHelpers.d.ts +51 -6
  121. package/dist/runtime/dom/evalHelpers.js +136 -26
  122. package/dist/runtime/dom/eventListeners.d.ts +2 -1
  123. package/dist/runtime/dom/eventListeners.js +174 -47
  124. package/dist/runtime/dom/formDiscovery.d.ts +1 -1
  125. package/dist/runtime/dom/formDiscovery.js +116 -16
  126. package/dist/runtime/dom/formFillHelpers/fill.d.ts +10 -0
  127. package/dist/runtime/dom/formFillHelpers/fill.js +125 -10
  128. package/dist/runtime/dom/formFillHelpers/index.d.ts +2 -2
  129. package/dist/runtime/dom/formFillHelpers/index.js +2 -2
  130. package/dist/runtime/dom/formFillHelpers/pressKey.js +14 -3
  131. package/dist/runtime/dom/formFillHelpers/scroll.d.ts +3 -0
  132. package/dist/runtime/dom/formFillHelpers/scroll.js +60 -18
  133. package/dist/runtime/dom/formFillHelpers/shared.d.ts +17 -0
  134. package/dist/runtime/dom/formFillHelpers/shared.js +25 -1
  135. package/dist/runtime/dom/formFillHelpers/stability.d.ts +20 -6
  136. package/dist/runtime/dom/formFillHelpers/stability.js +50 -19
  137. package/dist/runtime/dom/formSubmitHelpers.d.ts +3 -0
  138. package/dist/runtime/dom/formSubmitHelpers.js +89 -15
  139. package/dist/runtime/dom/frameLayout.d.ts +60 -0
  140. package/dist/runtime/dom/frameLayout.js +140 -0
  141. package/dist/runtime/dom/frameOrigin.d.ts +50 -0
  142. package/dist/runtime/dom/frameOrigin.js +62 -0
  143. package/dist/runtime/dom/frameScopedConnection.d.ts +92 -0
  144. package/dist/runtime/dom/frameScopedConnection.js +252 -0
  145. package/dist/runtime/dom/frameSelection.d.ts +1 -1
  146. package/dist/runtime/dom/frameSelection.js +2 -2
  147. package/dist/runtime/dom/frames.d.ts +25 -2
  148. package/dist/runtime/dom/frames.js +202 -63
  149. package/dist/runtime/dom/layout.d.ts +67 -0
  150. package/dist/runtime/dom/layout.js +333 -0
  151. package/dist/runtime/dom/listenerPageScripts.d.ts +66 -0
  152. package/dist/runtime/dom/listenerPageScripts.js +279 -0
  153. package/dist/runtime/dom/listenerSummary.d.ts +132 -11
  154. package/dist/runtime/dom/listenerSummary.js +344 -22
  155. package/dist/runtime/dom/pageActivity.d.ts +41 -0
  156. package/dist/runtime/dom/pageActivity.js +123 -0
  157. package/dist/runtime/dom/reactEventHelpers.d.ts +58 -2
  158. package/dist/runtime/dom/reactEventHelpers.js +212 -41
  159. package/dist/runtime/dom/targetNode.d.ts +80 -27
  160. package/dist/runtime/dom/targetNode.js +249 -33
  161. package/dist/runtime/dom/wait.d.ts +25 -0
  162. package/dist/runtime/dom/wait.js +199 -0
  163. package/dist/runtime/dom/waitCondition.d.ts +71 -0
  164. package/dist/runtime/dom/waitCondition.js +75 -0
  165. package/dist/runtime/page/emulation.d.ts +51 -0
  166. package/dist/runtime/page/emulation.js +80 -0
  167. package/dist/runtime/page/loadingState.d.ts +36 -0
  168. package/dist/runtime/page/loadingState.js +86 -0
  169. package/dist/runtime/page/navigation.d.ts +46 -2
  170. package/dist/runtime/page/navigation.js +69 -33
  171. package/dist/session/QueryCacheManager.d.ts +11 -1
  172. package/dist/session/QueryCacheManager.js +25 -3
  173. package/dist/session/chromeOwners.d.ts +34 -0
  174. package/dist/session/chromeOwners.js +51 -0
  175. package/dist/session/cleanup/staleSession.d.ts +11 -1
  176. package/dist/session/cleanup/staleSession.js +17 -6
  177. package/dist/session/cleanup/userCommands.js +2 -4
  178. package/dist/session/metadata.d.ts +5 -1
  179. package/dist/session/metadata.js +2 -1
  180. package/dist/session/paths.d.ts +77 -3
  181. package/dist/session/paths.js +111 -5
  182. package/dist/session/port.d.ts +31 -7
  183. package/dist/session/port.js +50 -43
  184. package/dist/session/portClaims.d.ts +66 -0
  185. package/dist/session/portClaims.js +284 -0
  186. package/dist/session/sessionList.d.ts +58 -0
  187. package/dist/session/sessionList.js +199 -0
  188. package/dist/session/sessionName.d.ts +46 -0
  189. package/dist/session/sessionName.js +97 -0
  190. package/dist/telemetry/a11y.d.ts +8 -3
  191. package/dist/telemetry/a11y.js +92 -28
  192. package/dist/telemetry/requestKinds.d.ts +32 -0
  193. package/dist/telemetry/requestKinds.js +61 -0
  194. package/dist/telemetry/requestState.d.ts +31 -0
  195. package/dist/telemetry/requestState.js +38 -0
  196. package/dist/types.d.ts +80 -3
  197. package/dist/ui/formatters/a11y.js +3 -0
  198. package/dist/ui/formatters/console/chronological.d.ts +8 -0
  199. package/dist/ui/formatters/console/chronological.js +17 -4
  200. package/dist/ui/formatters/console/json.js +3 -4
  201. package/dist/ui/formatters/console/shared.d.ts +12 -0
  202. package/dist/ui/formatters/console.d.ts +2 -2
  203. package/dist/ui/formatters/console.js +1 -1
  204. package/dist/ui/formatters/details.js +2 -1
  205. package/dist/ui/formatters/dom.d.ts +26 -14
  206. package/dist/ui/formatters/dom.js +65 -52
  207. package/dist/ui/formatters/form.js +29 -18
  208. package/dist/ui/formatters/layout.d.ts +31 -0
  209. package/dist/ui/formatters/layout.js +53 -0
  210. package/dist/ui/formatters/listeners.d.ts +3 -2
  211. package/dist/ui/formatters/listeners.js +73 -9
  212. package/dist/ui/formatters/networkHeaders.js +13 -0
  213. package/dist/ui/formatters/preview.js +2 -1
  214. package/dist/ui/formatters/requestStatus.d.ts +1 -17
  215. package/dist/ui/formatters/requestStatus.js +2 -30
  216. package/dist/ui/formatters/sessions.d.ts +12 -0
  217. package/dist/ui/formatters/sessions.js +40 -0
  218. package/dist/ui/formatters/status.d.ts +21 -2
  219. package/dist/ui/formatters/status.js +47 -10
  220. package/dist/ui/formatters/triggeredRequests.d.ts +36 -0
  221. package/dist/ui/formatters/triggeredRequests.js +65 -0
  222. package/dist/ui/formatting.d.ts +10 -0
  223. package/dist/ui/formatting.js +28 -36
  224. package/dist/ui/messages/chrome.d.ts +9 -0
  225. package/dist/ui/messages/chrome.js +17 -5
  226. package/dist/ui/messages/commands.d.ts +388 -14
  227. package/dist/ui/messages/commands.js +664 -21
  228. package/dist/ui/messages/consoleMessages.d.ts +10 -0
  229. package/dist/ui/messages/consoleMessages.js +17 -0
  230. package/dist/ui/messages/hints.js +2 -1
  231. package/dist/ui/messages/preview.js +5 -4
  232. package/dist/ui/messages/session.d.ts +16 -21
  233. package/dist/ui/messages/session.js +28 -26
  234. package/dist/ui/messages/sessionCommand.d.ts +43 -0
  235. package/dist/ui/messages/sessionCommand.js +52 -0
  236. package/dist/utils/async.d.ts +8 -0
  237. package/dist/utils/async.js +19 -0
  238. package/dist/utils/http.d.ts +22 -1
  239. package/dist/utils/http.js +28 -9
  240. package/dist/utils/selectorFilters.d.ts +36 -8
  241. package/dist/utils/selectorFilters.js +267 -53
  242. package/dist/utils/shellDetection.d.ts +8 -2
  243. package/dist/utils/shellDetection.js +120 -33
  244. package/dist/utils/suggestions.d.ts +26 -0
  245. package/dist/utils/suggestions.js +73 -0
  246. package/dist/utils/taskMappings.js +10 -0
  247. package/dist/utils/url.d.ts +12 -2
  248. package/dist/utils/url.js +69 -7
  249. package/package.json +1 -1
  250. package/dist/ui/formatters/sessionFormatters.d.ts +0 -58
  251. package/dist/ui/formatters/sessionFormatters.js +0 -121
@@ -1,5 +1,6 @@
1
1
  /**
2
- * `bdg page navigate|reload|back|forward` — move the session's page.
2
+ * `bdg page navigate|reload|back|forward` — move the session's page;
3
+ * `bdg page info` — where it is.
3
4
  */
4
5
  import type { Command } from 'commander';
5
6
  /**
@@ -1,12 +1,13 @@
1
1
  /**
2
- * `bdg page navigate|reload|back|forward` — move the session's page.
2
+ * `bdg page navigate|reload|back|forward` — move the session's page;
3
+ * `bdg page info` — where it is.
3
4
  */
4
- import { runCommand } from './shared/CommandRunner.js';
5
+ import { noActiveSessionError, runCommand } from './shared/CommandRunner.js';
5
6
  import { jsonOption } from './shared/commonOptions.js';
6
7
  import { javascriptNavigationError } from '../errors/messages.js';
7
- import { pageNavigate } from '../ipc/client.js';
8
+ import { getStatus, pageNavigate } from '../ipc/client.js';
8
9
  import { OutputFormatter } from '../ui/formatting.js';
9
- import { PAGE_ACTION_DESCRIPTIONS, PAGE_ACTION_DONE } from '../ui/messages/commands.js';
10
+ import { PAGE_ACTION_DESCRIPTIONS, PAGE_ACTION_DONE, PAGE_INFO_DESCRIPTION, pageLoadingWarning, } from '../ui/messages/commands.js';
10
11
  import { EXIT_CODES } from '../utils/exitCodes.js';
11
12
  import { validateUrl } from '../utils/url.js';
12
13
  /**
@@ -27,6 +28,8 @@ function formatPageResult(result) {
27
28
  ], 8);
28
29
  if (result.warning)
29
30
  fmt.text(`⚠ ${result.warning}`);
31
+ if (result.loading)
32
+ fmt.text(`⚠ ${pageLoadingWarning(result.loading)}`);
30
33
  return fmt.build();
31
34
  }
32
35
  /**
@@ -85,6 +88,32 @@ async function runPageAction(action, options, url) {
85
88
  return { success: true, data: response.data };
86
89
  }, options, formatPageResult);
87
90
  }
91
+ /**
92
+ * `bdg page info`: URL and title of the session page.
93
+ *
94
+ * @param options - Command options
95
+ */
96
+ async function showPageInfo(options) {
97
+ await runCommand(async () => {
98
+ const response = await getStatus();
99
+ if (response.status === 'error') {
100
+ return {
101
+ success: false,
102
+ error: response.error ?? 'Failed to read the page',
103
+ exitCode: EXIT_CODES.SOFTWARE_ERROR,
104
+ };
105
+ }
106
+ const page = response.data?.sessionPid ? response.data.pageState : undefined;
107
+ if (!page)
108
+ throw noActiveSessionError();
109
+ return { success: true, data: { url: page.url, title: page.title } };
110
+ }, options, (page) => new OutputFormatter()
111
+ .keyValueList([
112
+ ['URL', page.url],
113
+ ['Title', page.title],
114
+ ], 8)
115
+ .build());
116
+ }
88
117
  /**
89
118
  * Register the `page` command group.
90
119
  *
@@ -93,7 +122,14 @@ async function runPageAction(action, options, url) {
93
122
  export function registerPageCommands(program) {
94
123
  const page = program
95
124
  .command('page')
96
- .description('Navigate the session page: navigate <url>, reload, back, forward');
125
+ .description('The session page: info (URL and title), navigate <url>, reload, back, forward');
126
+ page
127
+ .command('info')
128
+ .description(PAGE_INFO_DESCRIPTION)
129
+ .addOption(jsonOption())
130
+ .action(async (options) => {
131
+ await showPageInfo(options);
132
+ });
97
133
  const withCommon = (command) => command
98
134
  .option('--no-wait', 'Return without waiting for the page to load')
99
135
  .addOption(jsonOption());
@@ -3,9 +3,9 @@
3
3
  */
4
4
  import { runCommand } from './shared/CommandRunner.js';
5
5
  import { jsonOption, showBothSectionsWhenBothRequested } from './shared/commonOptions.js';
6
- import { handleDaemonConnectionError, noteFollowConnected, } from './shared/daemonErrorHandler.js';
6
+ import { noteFollowConnected } from './shared/daemonErrorHandler.js';
7
7
  import { fetchPreviewOutput, createErrorResult, } from './shared/dataFetcher.js';
8
- import { setupFollowMode } from './shared/followMode.js';
8
+ import { followFetchFailure, setupFollowMode, } from './shared/followMode.js';
9
9
  import { handleValidationError } from './shared/handleValidationError.js';
10
10
  import { MAX_LAST_ITEMS, positiveIntRule, resourceTypeRule } from './shared/validation.js';
11
11
  import { filterByResourceType } from '../telemetry/filters.js';
@@ -79,21 +79,14 @@ async function runFollowMode(options, lastN, resourceTypes, baseOptions) {
79
79
  const showPreview = async () => {
80
80
  const result = await fetchAndFilterPreview(lastN, resourceTypes, peekSection(options));
81
81
  if (!result.success) {
82
- const errorResult = handleDaemonConnectionError(result.error, {
83
- json: options.json,
84
- follow: true,
85
- retryIntervalMs: 1000,
86
- exitCode: result.exitCode,
87
- });
88
- if (errorResult.shouldExit)
89
- process.exit(errorResult.exitCode);
90
- return;
82
+ return followFetchFailure(result, { json: options.json, retryIntervalMs: 1000 });
91
83
  }
92
84
  noteFollowConnected();
93
85
  if (!options.json)
94
86
  console.clear();
95
87
  const previewOptions = createPreviewOptions(baseOptions, resourceTypes, result.data.unfilteredNetworkCount);
96
88
  console.log(formatPreview(result.data.output, previewOptions));
89
+ return undefined;
97
90
  };
98
91
  await setupFollowMode(showPreview, {
99
92
  startMessage: followingPreviewMessage,
@@ -0,0 +1,8 @@
1
+ import type { Command } from 'commander';
2
+ /**
3
+ * Register the sessions command (lists running default and named sessions).
4
+ *
5
+ * @param program - Commander.js Command instance to register commands on
6
+ */
7
+ export declare function registerSessionsCommand(program: Command): void;
8
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { runCommand } from './shared/CommandRunner.js';
2
+ import { jsonOption } from './shared/commonOptions.js';
3
+ import { listRunningSessions } from '../session/sessionList.js';
4
+ import { formatSessionList } from '../ui/formatters/sessions.js';
5
+ /**
6
+ * Register the sessions command (lists running default and named sessions).
7
+ *
8
+ * @param program - Commander.js Command instance to register commands on
9
+ */
10
+ export function registerSessionsCommand(program) {
11
+ program
12
+ .command('sessions')
13
+ .description('List sessions (default and named) with their state, URL, port and PID, including crashed ones to clean up')
14
+ .addOption(jsonOption())
15
+ .action(async (options) => {
16
+ await runCommand(async () => ({ success: true, data: { sessions: await listRunningSessions() } }), options, formatSessionList);
17
+ });
18
+ }
19
+ //# sourceMappingURL=sessions.js.map
@@ -4,7 +4,7 @@ import { daemonNotRunningError, unknownError, genericError, commandTimedOutError
4
4
  import { IPCEarlyCloseError, IPCTimeoutError } from '../../ipc/transport/IPCError.js';
5
5
  import { OutputBuilder, buildSuccessResponse } from '../../ui/OutputBuilder.js';
6
6
  import { escapeControlChars } from '../../ui/formatting.js';
7
- import { STOP_MESSAGES } from '../../ui/messages/session.js';
7
+ import { noActiveSessionMessage, startSessionSuggestion } from '../../ui/messages/sessionCommand.js';
8
8
  import { getErrorExitCode, getErrorMessage } from '../../utils/errors.js';
9
9
  import { EXIT_CODES } from '../../utils/exitCodes.js';
10
10
  /**
@@ -13,7 +13,7 @@ import { EXIT_CODES } from '../../utils/exitCodes.js';
13
13
  * @returns Command error (exit 83) with how to start one
14
14
  */
15
15
  export function noActiveSessionError() {
16
- return new CommandError(STOP_MESSAGES.DAEMON_NOT_RUNNING, { suggestion: 'Start a session with: bdg <url>' }, EXIT_CODES.RESOURCE_NOT_FOUND);
16
+ return new CommandError(noActiveSessionMessage(), { suggestion: startSessionSuggestion() }, EXIT_CODES.RESOURCE_NOT_FOUND);
17
17
  }
18
18
  /**
19
19
  * Execute an async function and output JSON result with proper error handling.
@@ -168,8 +168,8 @@ export async function runCommand(handler, options, formatter) {
168
168
  const errorMessage = getErrorMessage(error);
169
169
  if (isDaemonConnectionError(error)) {
170
170
  if (options.json) {
171
- console.log(JSON.stringify(OutputBuilder.buildJsonError(STOP_MESSAGES.DAEMON_NOT_RUNNING, {
172
- suggestion: 'Start a session with: bdg <url>',
171
+ console.log(JSON.stringify(OutputBuilder.buildJsonError(noActiveSessionMessage(), {
172
+ suggestion: startSessionSuggestion(),
173
173
  exitCode: EXIT_CODES.RESOURCE_NOT_FOUND,
174
174
  }), null, 2));
175
175
  }
@@ -7,7 +7,7 @@ import { validateIPCResponse } from '../../ipc/index.js';
7
7
  import { IPCConnectionError, IPCEarlyCloseError, IPCTimeoutError, } from '../../ipc/transport/IPCError.js';
8
8
  import { isConnectionError } from '../../ipc/utils/errors.js';
9
9
  import { createLogger } from '../../ui/logging/index.js';
10
- import { STOP_MESSAGES } from '../../ui/messages/session.js';
10
+ import { noActiveSessionMessage } from '../../ui/messages/sessionCommand.js';
11
11
  import { getExitCodeForConnectionError } from '../../utils/errorMapping.js';
12
12
  import { getErrorMessage } from '../../utils/errors.js';
13
13
  import { EXIT_CODES } from '../../utils/exitCodes.js';
@@ -42,7 +42,7 @@ export async function fetchPreviewOutput(query = {}) {
42
42
  log.debug(`Daemon unreachable: ${getErrorMessage(error)}`);
43
43
  return {
44
44
  success: false,
45
- error: STOP_MESSAGES.DAEMON_NOT_RUNNING,
45
+ error: noActiveSessionMessage(),
46
46
  exitCode: EXIT_CODES.RESOURCE_NOT_FOUND,
47
47
  };
48
48
  }
@@ -4,6 +4,25 @@
4
4
  * Provides a unified pattern for commands that continuously poll
5
5
  * and display updates (like tail -f behavior).
6
6
  */
7
+ /** What a refresh asks for: nothing to keep following, or the exit code to stop with */
8
+ export type FollowPoll = {
9
+ exitCode: number;
10
+ } | undefined;
11
+ /**
12
+ * Report a failed fetch in follow mode: a lost connection is reported and
13
+ * retried while the session was seen before, otherwise follow mode stops.
14
+ *
15
+ * @param failure - The fetch's error and exit code
16
+ * @param options - JSON output and the retry interval shown
17
+ * @returns The exit code to stop with, or undefined to keep following
18
+ */
19
+ export declare function followFetchFailure(failure: {
20
+ error: string;
21
+ exitCode?: number | undefined;
22
+ }, options: {
23
+ json?: boolean | undefined;
24
+ retryIntervalMs: number;
25
+ }): FollowPoll;
7
26
  /**
8
27
  * Options for configuring follow mode behavior.
9
28
  */
@@ -24,6 +43,7 @@ export interface FollowModeOptions {
24
43
  * - First refresh call (awaited)
25
44
  * - Periodic interval-based refresh
26
45
  * - SIGINT handler for graceful shutdown
46
+ * - Stopping with the exit code a refresh returns (e.g. the session is gone)
27
47
  *
28
48
  * @param refreshFn - Async function to call on each refresh cycle
29
49
  * @param options - Configuration options for follow mode
@@ -43,5 +63,5 @@ export interface FollowModeOptions {
43
63
  * );
44
64
  * ```
45
65
  */
46
- export declare function setupFollowMode(refreshFn: () => Promise<void>, options: FollowModeOptions): Promise<void>;
66
+ export declare function setupFollowMode(refreshFn: () => Promise<FollowPoll>, options: FollowModeOptions): Promise<void>;
47
67
  //# sourceMappingURL=followMode.d.ts.map
@@ -4,9 +4,29 @@
4
4
  * Provides a unified pattern for commands that continuously poll
5
5
  * and display updates (like tail -f behavior).
6
6
  */
7
+ import { handleDaemonConnectionError } from './daemonErrorHandler.js';
7
8
  import { genericError } from '../../errors/messages.js';
8
9
  import { getErrorMessage } from '../../utils/errors.js';
9
10
  import { EXIT_CODES } from '../../utils/exitCodes.js';
11
+ /**
12
+ * Report a failed fetch in follow mode: a lost connection is reported and
13
+ * retried while the session was seen before, otherwise follow mode stops.
14
+ *
15
+ * @param failure - The fetch's error and exit code
16
+ * @param options - JSON output and the retry interval shown
17
+ * @returns The exit code to stop with, or undefined to keep following
18
+ */
19
+ export function followFetchFailure(failure, options) {
20
+ const result = handleDaemonConnectionError(failure.error, {
21
+ json: options.json,
22
+ follow: true,
23
+ retryIntervalMs: options.retryIntervalMs,
24
+ exitCode: failure.exitCode,
25
+ });
26
+ return result.shouldExit
27
+ ? { exitCode: result.exitCode ?? EXIT_CODES.RESOURCE_NOT_FOUND }
28
+ : undefined;
29
+ }
10
30
  /**
11
31
  * Sets up follow mode with periodic refresh and graceful shutdown.
12
32
  *
@@ -16,6 +36,7 @@ import { EXIT_CODES } from '../../utils/exitCodes.js';
16
36
  * - First refresh call (awaited)
17
37
  * - Periodic interval-based refresh
18
38
  * - SIGINT handler for graceful shutdown
39
+ * - Stopping with the exit code a refresh returns (e.g. the session is gone)
19
40
  *
20
41
  * @param refreshFn - Async function to call on each refresh cycle
21
42
  * @param options - Configuration options for follow mode
@@ -37,10 +58,16 @@ import { EXIT_CODES } from '../../utils/exitCodes.js';
37
58
  */
38
59
  export async function setupFollowMode(refreshFn, options) {
39
60
  const { startMessage, stopMessage, intervalMs = 1000 } = options;
61
+ const stopIfAsked = (poll) => {
62
+ if (poll)
63
+ process.exit(poll.exitCode);
64
+ };
40
65
  console.error(startMessage());
41
- await refreshFn();
66
+ stopIfAsked(await refreshFn());
42
67
  const intervalId = setInterval(() => {
43
- refreshFn().catch((error) => {
68
+ refreshFn()
69
+ .then(stopIfAsked)
70
+ .catch((error) => {
44
71
  console.error(genericError(getErrorMessage(error)));
45
72
  });
46
73
  }, intervalMs);
@@ -4,8 +4,8 @@
4
4
  *
5
5
  * For `CommandError`, emits either a JSON envelope (when `json=true`) or
6
6
  * a human-readable message + suggestion, then exits with the error's own
7
- * exit code. For anything else, prints the message and exits with
8
- * `INVALID_ARGUMENTS`.
7
+ * exit code. For anything else, prints the message (as an envelope with
8
+ * `--json`) and exits with `INVALID_ARGUMENTS`.
9
9
  *
10
10
  * @param error - Error thrown from validation code
11
11
  * @param json - Whether the caller is in `--json` output mode
@@ -9,8 +9,8 @@ import { EXIT_CODES } from '../../utils/exitCodes.js';
9
9
  *
10
10
  * For `CommandError`, emits either a JSON envelope (when `json=true`) or
11
11
  * a human-readable message + suggestion, then exits with the error's own
12
- * exit code. For anything else, prints the message and exits with
13
- * `INVALID_ARGUMENTS`.
12
+ * exit code. For anything else, prints the message (as an envelope with
13
+ * `--json`) and exits with `INVALID_ARGUMENTS`.
14
14
  *
15
15
  * @param error - Error thrown from validation code
16
16
  * @param json - Whether the caller is in `--json` output mode
@@ -33,7 +33,16 @@ export function handleValidationError(error, json) {
33
33
  }
34
34
  process.exit(error.exitCode);
35
35
  }
36
- console.error(genericError(error instanceof Error ? error.message : String(error)));
36
+ const message = error instanceof Error ? error.message : String(error);
37
+ if (json) {
38
+ const envelope = OutputBuilder.buildJsonError(message, {
39
+ exitCode: EXIT_CODES.INVALID_ARGUMENTS,
40
+ });
41
+ console.log(JSON.stringify(envelope, null, 2));
42
+ }
43
+ else {
44
+ console.error(genericError(message));
45
+ }
37
46
  process.exit(EXIT_CODES.INVALID_ARGUMENTS);
38
47
  }
39
48
  //# sourceMappingURL=handleValidationError.js.map
@@ -25,6 +25,8 @@ export interface BaseOptions {
25
25
  json?: boolean;
26
26
  /** Hide tips and hints (`-q`, accepted by every command) */
27
27
  quiet?: boolean;
28
+ /** Named session to act on (`--session`, accepted by every command) */
29
+ session?: string;
28
30
  }
29
31
  /**
30
32
  * Options for commands with verbose output.
@@ -58,6 +60,8 @@ export interface CleanupOptions {
58
60
  removeOutput?: boolean;
59
61
  /** Aggressive cleanup - kill all Chrome processes */
60
62
  aggressive?: boolean;
63
+ /** Also delete the named session's directory (profile, logs, port) */
64
+ purge?: boolean;
61
65
  }
62
66
  /**
63
67
  * Options for commands with raw output mode.
@@ -138,12 +142,17 @@ export type DetailsCommandOptions = BaseOptions & {
138
142
  /** Options for DOM query command */
139
143
  export type DomQueryCommandOptions = BaseOptions;
140
144
  /** Options for DOM get command */
141
- export type DomGetCommandOptions = BaseOptions & RawOptions & SelectionOptions;
145
+ export type DomGetCommandOptions = BaseOptions & RawOptions & SelectionOptions & {
146
+ /** All of the element's text instead of its first 500 characters (semantic output) */
147
+ full?: boolean;
148
+ /** Which match of the selector (0-based); `--nth` is its alias */
149
+ index?: number;
150
+ };
142
151
  /** Options for DOM screenshot command */
143
152
  export type DomScreenshotCommandOptions = BaseOptions & ScreenshotOptions;
144
153
  /** Options for DOM eval command */
145
154
  export interface DomEvalCommandOptions extends BaseOptions {
146
- /** Iframe to evaluate in: index, name/id attribute, or part of the URL */
155
+ /** Iframe to evaluate in: index, name/id attribute, or part of the name, id or URL */
147
156
  frame?: string;
148
157
  }
149
158
  /** Options for DOM frames command */
@@ -218,13 +227,35 @@ export interface ScrollCommandOptions extends BaseOptions, IndexOptions {
218
227
  * Options for `dom listeners`.
219
228
  */
220
229
  export interface ListenersCommandOptions extends BaseOptions, IndexOptions {
221
- /** Only these event types (from --type, comma-separated) */
230
+ /** Only these event types (from --type, comma-separated, repeatable) */
222
231
  type?: string[];
232
+ /** List every listener of framework roots */
233
+ all?: boolean;
234
+ }
235
+ /**
236
+ * Options for `dom layout`.
237
+ */
238
+ export type LayoutCommandOptions = BaseOptions & IndexOptions;
239
+ /** Options for `bdg dom wait` */
240
+ export interface WaitCommandOptions extends BaseOptions {
241
+ /** Text a match must contain */
242
+ text?: string;
243
+ /** Wait for the matches to be gone */
244
+ gone?: boolean;
245
+ /** Only count visible matches */
246
+ visible?: boolean;
247
+ /** Wait for document.readyState to be complete */
248
+ load?: boolean;
249
+ /** Give up after this many milliseconds */
250
+ timeout: number;
223
251
  }
224
252
  /** Options for A11y tree command */
225
253
  export type A11yTreeCommandOptions = BaseOptions;
226
254
  /** Options for A11y query command */
227
- export type A11yQueryCommandOptions = BaseOptions;
255
+ export interface A11yQueryCommandOptions extends BaseOptions {
256
+ /** Matches to list (0 = all) */
257
+ limit?: number;
258
+ }
228
259
  /** Options for A11y describe command */
229
260
  export type A11yDescribeCommandOptions = BaseOptions;
230
261
  /** Options for CDP command */
@@ -274,9 +305,13 @@ export interface SessionStartOptions {
274
305
  json?: boolean | undefined;
275
306
  /** Custom Chrome flags (e.g., ['--ignore-certificate-errors']) */
276
307
  chromeFlags: string[] | undefined;
308
+ /** Viewport size to emulate (`--viewport`) */
309
+ viewport?: ViewportSize | undefined;
310
+ /** `prefers-color-scheme` to emulate (`--color-scheme`) */
311
+ colorScheme?: ColorScheme | undefined;
277
312
  }
278
313
  export type { ConsoleLevel } from '../../types.js';
279
- import type { ConsoleLevel } from '../../types.js';
314
+ import type { ColorScheme, ConsoleLevel, ViewportSize } from '../../types.js';
280
315
  /**
281
316
  * Options for console command.
282
317
  * Supports smart summary (default), list view (--list), and streaming (--follow).
@@ -8,15 +8,17 @@ import { timeoutError } from './CommandRunner.js';
8
8
  import { landingPage } from './landingPage.js';
9
9
  import { DaemonError, SessionDirError } from '../../daemon/errors.js';
10
10
  import { launchDaemon } from '../../daemon/launcher.js';
11
- import { LAUNCHED_CHROME_DESCRIPTION, sessionAlreadyRunningError, ALREADY_RUNNING_SUGGESTION, sessionTargetMismatchError, daemonNotRunningError, invalidResponseError, genericError, } from '../../errors/messages.js';
11
+ import { LAUNCHED_CHROME_DESCRIPTION, sessionAlreadyRunningError, alreadyRunningSuggestion, sessionTargetMismatchError, daemonNotRunningError, invalidResponseError, genericError, } from '../../errors/messages.js';
12
12
  import { startSession as sendStartSessionRequest } from '../../ipc/client.js';
13
13
  import { IPCErrorCode, } from '../../ipc/index.js';
14
14
  import { IPCTimeoutError } from '../../ipc/transport/index.js';
15
15
  import { isConnectionError } from '../../ipc/utils/errors.js';
16
+ import { getSessionName } from '../../session/paths.js';
16
17
  import { OutputBuilder, buildSuccessResponse } from '../../ui/OutputBuilder.js';
17
18
  import { escapeControlChars, joinLines } from '../../ui/formatting.js';
18
19
  import { createLogger } from '../../ui/logging/index.js';
19
20
  import { startNotices } from '../../ui/messages/session.js';
21
+ import { noActiveSessionMessage } from '../../ui/messages/sessionCommand.js';
20
22
  import { delay } from '../../utils/async.js';
21
23
  import { getExitCodeForIPCError } from '../../utils/errorMapping.js';
22
24
  import { getErrorMessage } from '../../utils/errors.js';
@@ -111,6 +113,8 @@ async function requestSession(url, options, telemetry) {
111
113
  headless: options.headless,
112
114
  chromeWsUrl: options.chromeWsUrl,
113
115
  chromeFlags: options.chromeFlags,
116
+ viewport: options.viewport,
117
+ colorScheme: options.colorScheme,
114
118
  }));
115
119
  if (response.status === 'error')
116
120
  return describeStartFailure(response, options);
@@ -139,7 +143,7 @@ async function requestSession(url, options, telemetry) {
139
143
  if (isConnectionError(error)) {
140
144
  return {
141
145
  ok: false,
142
- error: 'No active session (daemon not running)',
146
+ error: `${noActiveSessionMessage()} (daemon not running)`,
143
147
  human: daemonNotRunningError({ suggestStatus: true, suggestRetry: true }),
144
148
  exitCode: EXIT_CODES.RESOURCE_NOT_FOUND,
145
149
  retryable: true,
@@ -189,7 +193,7 @@ function describeStartFailure(response, options) {
189
193
  human: sessionAlreadyRunningError(pid, duration ? duration * 1000 : 0, targetUrl),
190
194
  exitCode,
191
195
  errorCode: response.errorCode,
192
- details: { ...details, suggestion: ALREADY_RUNNING_SUGGESTION },
196
+ details: { ...details, suggestion: alreadyRunningSuggestion() },
193
197
  };
194
198
  }
195
199
  if (response.errorCode === IPCErrorCode.SESSION_TARGET_MISMATCH) {
@@ -242,11 +246,14 @@ function reportStartOutcome(outcome, options) {
242
246
  }
243
247
  const { data } = outcome;
244
248
  const autoStopAt = options.timeout !== undefined ? new Date(Date.now() + options.timeout * 1000) : undefined;
249
+ const session = getSessionName() ?? undefined;
245
250
  if (options.json) {
246
251
  const result = {
252
+ ...(session && { session }),
247
253
  targetUrl: data.targetUrl,
248
254
  ...(data.targetTitle !== undefined && { targetTitle: data.targetTitle }),
249
255
  ...(data.documentStatus !== undefined && { documentStatus: data.documentStatus }),
256
+ ...(data.loading && { loading: data.loading }),
250
257
  port: data.port,
251
258
  ...(data.chromePid > 0 ? { chromePid: data.chromePid } : { externalChrome: true }),
252
259
  daemonPid: data.daemonPid,
@@ -258,7 +265,9 @@ function reportStartOutcome(outcome, options) {
258
265
  const page = {
259
266
  url: data.targetUrl,
260
267
  ...(data.documentStatus !== undefined && { documentStatus: data.documentStatus }),
268
+ ...(data.loading && { loading: data.loading }),
261
269
  ...(autoStopAt && { autoStopAt }),
270
+ ...(session && { session }),
262
271
  };
263
272
  const text = options.quiet
264
273
  ? [`Session started: ${data.targetUrl}`, ...startNotices(page)].join('\n')
@@ -49,12 +49,13 @@ export declare function screenshotFormatOption(value: string): 'png' | 'jpeg';
49
49
  export declare function consoleLevelOption(value: string): ConsoleLevel;
50
50
  /**
51
51
  * Commander parser for `dom listeners --type`: comma-separated event types
52
- * (case-sensitive, like `addEventListener`).
52
+ * (case-sensitive, like `addEventListener`); repeated options add up.
53
53
  *
54
54
  * @param value - Raw option value, e.g. "click,keydown"
55
+ * @param previous - Types from earlier `--type` options
55
56
  * @returns Event types
56
57
  * @throws InvalidArgumentError (exit 81) when no type is given
57
58
  */
58
- export declare function eventTypesOption(value: string): string[];
59
+ export declare function eventTypesOption(value: string, previous?: string[]): string[];
59
60
  export declare function resourceTypeRule(): ValidationRule<Protocol.Network.ResourceType[]>;
60
61
  //# sourceMappingURL=validation.d.ts.map
@@ -145,16 +145,17 @@ export function consoleLevelOption(value) {
145
145
  }
146
146
  /**
147
147
  * Commander parser for `dom listeners --type`: comma-separated event types
148
- * (case-sensitive, like `addEventListener`).
148
+ * (case-sensitive, like `addEventListener`); repeated options add up.
149
149
  *
150
150
  * @param value - Raw option value, e.g. "click,keydown"
151
+ * @param previous - Types from earlier `--type` options
151
152
  * @returns Event types
152
153
  * @throws InvalidArgumentError (exit 81) when no type is given
153
154
  */
154
- export function eventTypesOption(value) {
155
+ export function eventTypesOption(value, previous = []) {
155
156
  const types = parseCommaSeparated(value);
156
157
  if (types.length > 0)
157
- return types;
158
+ return [...new Set([...previous, ...types])];
158
159
  throw new InvalidArgumentError('Give at least one event type, e.g. click or click,keydown.');
159
160
  }
160
161
  function parseCommaSeparated(value) {
@@ -1,4 +1,34 @@
1
1
  import { type Command } from 'commander';
2
+ import type { ColorScheme, ViewportSize } from '../types.js';
3
+ /**
4
+ * Parsed command-line flags shared by the start subcommands.
5
+ */
6
+ export interface CollectorOptions {
7
+ /** Chrome debugging port as provided by the user. */
8
+ port: string;
9
+ /** Optional auto-stop timeout (seconds, string form). */
10
+ timeout?: string;
11
+ /** Custom Chrome profile directory path. */
12
+ userDataDir?: string;
13
+ /** When true, disables default filtering of noisy data. */
14
+ all?: boolean;
15
+ /** Maximum response body size in megabytes (default: 5MB). */
16
+ maxBodySize?: string;
17
+ /** Launch Chrome in headless mode. Default: true if no display, false if display available. */
18
+ headless?: boolean;
19
+ /** WebSocket URL for connecting to existing Chrome instance (skips Chrome launch). */
20
+ chromeWsUrl?: string;
21
+ /** Quiet mode - suppress verbose landing page output for AI agents. */
22
+ quiet?: boolean;
23
+ /** Print the result as a JSON envelope. */
24
+ json?: boolean;
25
+ /** Custom Chrome flags (space-separated string). */
26
+ chromeFlags?: string;
27
+ /** Viewport size, e.g. `1280x800`. */
28
+ viewport?: string;
29
+ /** `prefers-color-scheme` to emulate: light or dark. */
30
+ colorScheme?: string;
31
+ }
2
32
  /**
3
33
  * Expand a leading `~/` in a path to the user's home directory.
4
34
  * Chrome itself does not expand `~`, so bdg normalizes it for users.
@@ -16,6 +46,30 @@ export declare function extractUserDataDirFromFlags(flags: string[]): {
16
46
  userDataDir: string | undefined;
17
47
  rest: string[];
18
48
  };
49
+ /**
50
+ * Apply shared telemetry options to a command
51
+ *
52
+ * @param command - Commander.js Command instance to apply options to
53
+ * @returns The modified Command instance with all telemetry options applied
54
+ */
55
+ export declare function applyCollectorOptions(command: Command): Command;
56
+ /**
57
+ * Parse a `--viewport` value: width and height in CSS px joined by `x`
58
+ * (`1280x800`; `X`, `×` and `,` work too).
59
+ *
60
+ * @param value - Option value
61
+ * @returns Viewport size
62
+ * @throws CommandError (81) for anything else, or a side outside 1-10000
63
+ */
64
+ export declare function parseViewport(value: string): ViewportSize;
65
+ /**
66
+ * Parse a `--color-scheme` value (case-insensitive).
67
+ *
68
+ * @param value - Option value
69
+ * @returns The scheme
70
+ * @throws CommandError (81) for another value, suggesting the closest one
71
+ */
72
+ export declare function parseColorScheme(value: string): ColorScheme;
19
73
  /**
20
74
  * Reject a subcommand typed without its group (`bdg query x` for
21
75
  * `bdg dom query x`) before Commander reads it as a start URL with extra
@@ -33,4 +87,13 @@ export declare function assertNotGroupSubcommand(program: Command, argv: string[
33
87
  * @returns void
34
88
  */
35
89
  export declare function registerStartCommands(program: Command): void;
90
+ /**
91
+ * Options given that only apply to a Chrome bdg launches. `--headless` has a
92
+ * default, so it counts only when given on the command line.
93
+ *
94
+ * @param options - Parsed options
95
+ * @param program - Command the options were parsed by
96
+ * @returns The conflicting flags, e.g. ["--port", "--headless"]
97
+ */
98
+ export declare function launchOptionConflicts(options: CollectorOptions, program: Command): string[];
36
99
  //# sourceMappingURL=start.d.ts.map