@monoes/monobrowse 1.0.11 → 1.0.12

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 (220) hide show
  1. package/dist/src/__tests__/adapters.test.js +5 -2
  2. package/dist/src/__tests__/adapters.test.js.map +1 -1
  3. package/dist/src/__tests__/batch-eval-parsing.test.js +4 -2
  4. package/dist/src/__tests__/batch-eval-parsing.test.js.map +1 -1
  5. package/dist/src/__tests__/box-model.test.js +9 -5
  6. package/dist/src/__tests__/box-model.test.js.map +1 -1
  7. package/dist/src/__tests__/browser-launch.test.d.ts +10 -0
  8. package/dist/src/__tests__/browser-launch.test.d.ts.map +1 -1
  9. package/dist/src/__tests__/browser-launch.test.js +17 -10
  10. package/dist/src/__tests__/browser-launch.test.js.map +1 -1
  11. package/dist/src/__tests__/cdp-client.test.js +9 -3
  12. package/dist/src/__tests__/cdp-client.test.js.map +1 -1
  13. package/dist/src/__tests__/close-browser.test.d.ts +13 -0
  14. package/dist/src/__tests__/close-browser.test.d.ts.map +1 -1
  15. package/dist/src/__tests__/close-browser.test.js +5 -5
  16. package/dist/src/__tests__/close-browser.test.js.map +1 -1
  17. package/dist/src/__tests__/console-log.test.js +17 -6
  18. package/dist/src/__tests__/console-log.test.js.map +1 -1
  19. package/dist/src/__tests__/find.test.js +26 -6
  20. package/dist/src/__tests__/find.test.js.map +1 -1
  21. package/dist/src/__tests__/frame-command.test.js +9 -3
  22. package/dist/src/__tests__/frame-command.test.js.map +1 -1
  23. package/dist/src/__tests__/open-url-navigate-error.test.js +1 -3
  24. package/dist/src/__tests__/open-url-navigate-error.test.js.map +1 -1
  25. package/dist/src/__tests__/output.test.js +1 -1
  26. package/dist/src/__tests__/output.test.js.map +1 -1
  27. package/dist/src/__tests__/reap-idle-browser.test.d.ts +15 -0
  28. package/dist/src/__tests__/reap-idle-browser.test.d.ts.map +1 -0
  29. package/dist/src/__tests__/reap-idle-browser.test.js +238 -0
  30. package/dist/src/__tests__/reap-idle-browser.test.js.map +1 -0
  31. package/dist/src/__tests__/ref-cache.test.js +18 -10
  32. package/dist/src/__tests__/ref-cache.test.js.map +1 -1
  33. package/dist/src/__tests__/session-state.test.d.ts +8 -0
  34. package/dist/src/__tests__/session-state.test.d.ts.map +1 -1
  35. package/dist/src/__tests__/session-state.test.js +10 -10
  36. package/dist/src/__tests__/session-state.test.js.map +1 -1
  37. package/dist/src/__tests__/snapshot.test.js +44 -14
  38. package/dist/src/__tests__/snapshot.test.js.map +1 -1
  39. package/dist/src/__tests__/storage-eval.test.js +14 -6
  40. package/dist/src/__tests__/storage-eval.test.js.map +1 -1
  41. package/dist/src/__tests__/tabs.test.js +25 -9
  42. package/dist/src/__tests__/tabs.test.js.map +1 -1
  43. package/dist/src/browser/action-builder/analyzer.d.ts +1 -1
  44. package/dist/src/browser/action-builder/analyzer.d.ts.map +1 -1
  45. package/dist/src/browser/action-builder/analyzer.js +25 -9
  46. package/dist/src/browser/action-builder/analyzer.js.map +1 -1
  47. package/dist/src/browser/action-builder/types.d.ts.map +1 -1
  48. package/dist/src/browser/actions.d.ts +1 -1
  49. package/dist/src/browser/actions.d.ts.map +1 -1
  50. package/dist/src/browser/actions.js +16 -6
  51. package/dist/src/browser/actions.js.map +1 -1
  52. package/dist/src/browser/adapters/gemini.d.ts.map +1 -1
  53. package/dist/src/browser/adapters/gemini.js.map +1 -1
  54. package/dist/src/browser/adapters/google.d.ts.map +1 -1
  55. package/dist/src/browser/adapters/google.js.map +1 -1
  56. package/dist/src/browser/adapters/index.d.ts.map +1 -1
  57. package/dist/src/browser/adapters/index.js +3 -3
  58. package/dist/src/browser/adapters/index.js.map +1 -1
  59. package/dist/src/browser/adapters/instagram.d.ts.map +1 -1
  60. package/dist/src/browser/adapters/instagram.js.map +1 -1
  61. package/dist/src/browser/adapters/linkedin.d.ts.map +1 -1
  62. package/dist/src/browser/adapters/linkedin.js.map +1 -1
  63. package/dist/src/browser/adapters/microsoft.d.ts.map +1 -1
  64. package/dist/src/browser/adapters/microsoft.js.map +1 -1
  65. package/dist/src/browser/adapters/x.d.ts.map +1 -1
  66. package/dist/src/browser/adapters/x.js.map +1 -1
  67. package/dist/src/browser/browser.d.ts +30 -0
  68. package/dist/src/browser/browser.d.ts.map +1 -1
  69. package/dist/src/browser/browser.js +122 -15
  70. package/dist/src/browser/browser.js.map +1 -1
  71. package/dist/src/browser/cdp.d.ts.map +1 -1
  72. package/dist/src/browser/cdp.js +21 -8
  73. package/dist/src/browser/cdp.js.map +1 -1
  74. package/dist/src/browser/console-log.d.ts.map +1 -1
  75. package/dist/src/browser/console-log.js +2 -2
  76. package/dist/src/browser/console-log.js.map +1 -1
  77. package/dist/src/browser/dashboard/server.d.ts.map +1 -1
  78. package/dist/src/browser/dashboard/server.js +29 -19
  79. package/dist/src/browser/dashboard/server.js.map +1 -1
  80. package/dist/src/browser/dashboard/ui.html +153 -165
  81. package/dist/src/browser/dialog.d.ts.map +1 -1
  82. package/dist/src/browser/dialog.js +3 -1
  83. package/dist/src/browser/dialog.js.map +1 -1
  84. package/dist/src/browser/emulation.d.ts.map +1 -1
  85. package/dist/src/browser/emulation.js +21 -6
  86. package/dist/src/browser/emulation.js.map +1 -1
  87. package/dist/src/browser/find.d.ts +4 -4
  88. package/dist/src/browser/find.d.ts.map +1 -1
  89. package/dist/src/browser/find.js +14 -6
  90. package/dist/src/browser/find.js.map +1 -1
  91. package/dist/src/browser/har.d.ts.map +1 -1
  92. package/dist/src/browser/har.js +14 -7
  93. package/dist/src/browser/har.js.map +1 -1
  94. package/dist/src/browser/index.d.ts +16 -16
  95. package/dist/src/browser/index.d.ts.map +1 -1
  96. package/dist/src/browser/index.js +16 -16
  97. package/dist/src/browser/index.js.map +1 -1
  98. package/dist/src/browser/network.d.ts.map +1 -1
  99. package/dist/src/browser/network.js +14 -4
  100. package/dist/src/browser/network.js.map +1 -1
  101. package/dist/src/browser/pdf.d.ts.map +1 -1
  102. package/dist/src/browser/pdf.js +3 -3
  103. package/dist/src/browser/pdf.js.map +1 -1
  104. package/dist/src/browser/profiler.d.ts.map +1 -1
  105. package/dist/src/browser/profiler.js +10 -5
  106. package/dist/src/browser/profiler.js.map +1 -1
  107. package/dist/src/browser/record.d.ts +1 -1
  108. package/dist/src/browser/record.d.ts.map +1 -1
  109. package/dist/src/browser/record.js +18 -7
  110. package/dist/src/browser/record.js.map +1 -1
  111. package/dist/src/browser/ref-cache.d.ts.map +1 -1
  112. package/dist/src/browser/ref-cache.js +9 -4
  113. package/dist/src/browser/ref-cache.js.map +1 -1
  114. package/dist/src/browser/screenshot.d.ts.map +1 -1
  115. package/dist/src/browser/screenshot.js +11 -7
  116. package/dist/src/browser/screenshot.js.map +1 -1
  117. package/dist/src/browser/session.d.ts +1 -1
  118. package/dist/src/browser/session.d.ts.map +1 -1
  119. package/dist/src/browser/session.js +27 -8
  120. package/dist/src/browser/session.js.map +1 -1
  121. package/dist/src/browser/snapshot.d.ts +1 -1
  122. package/dist/src/browser/snapshot.d.ts.map +1 -1
  123. package/dist/src/browser/snapshot.js +8 -4
  124. package/dist/src/browser/snapshot.js.map +1 -1
  125. package/dist/src/browser/storage.d.ts.map +1 -1
  126. package/dist/src/browser/storage.js.map +1 -1
  127. package/dist/src/browser/tabs.d.ts.map +1 -1
  128. package/dist/src/browser/tabs.js +9 -3
  129. package/dist/src/browser/tabs.js.map +1 -1
  130. package/dist/src/browser/trace.d.ts.map +1 -1
  131. package/dist/src/browser/trace.js +3 -3
  132. package/dist/src/browser/trace.js.map +1 -1
  133. package/dist/src/browser/types.d.ts.map +1 -1
  134. package/dist/src/browser/types.js +23 -4
  135. package/dist/src/browser/types.js.map +1 -1
  136. package/dist/src/browser/vitals.d.ts.map +1 -1
  137. package/dist/src/browser/vitals.js +1 -1
  138. package/dist/src/browser/vitals.js.map +1 -1
  139. package/dist/src/browser/wait.d.ts.map +1 -1
  140. package/dist/src/browser/wait.js +11 -5
  141. package/dist/src/browser/wait.js.map +1 -1
  142. package/dist/src/cli/action.d.ts.map +1 -1
  143. package/dist/src/cli/action.js +14 -11
  144. package/dist/src/cli/action.js.map +1 -1
  145. package/dist/src/cli/commands.d.ts.map +1 -1
  146. package/dist/src/cli/commands.js +453 -159
  147. package/dist/src/cli/commands.js.map +1 -1
  148. package/dist/src/cli/output.js +5 -5
  149. package/dist/src/cli/output.js.map +1 -1
  150. package/dist/src/cli/platform.d.ts.map +1 -1
  151. package/dist/src/cli/platform.js +15 -11
  152. package/dist/src/cli/platform.js.map +1 -1
  153. package/dist/src/cli/types.d.ts +1 -1
  154. package/dist/src/cli/types.d.ts.map +1 -1
  155. package/dist/src/cli.js +21 -9
  156. package/dist/src/cli.js.map +1 -1
  157. package/dist/src/index.d.ts +2 -2
  158. package/dist/src/index.d.ts.map +1 -1
  159. package/dist/src/index.js +2 -2
  160. package/dist/src/index.js.map +1 -1
  161. package/dist/tsconfig.tsbuildinfo +1 -1
  162. package/package.json +1 -1
  163. package/src/__tests__/adapters.test.ts +15 -8
  164. package/src/__tests__/batch-eval-parsing.test.ts +4 -2
  165. package/src/__tests__/box-model.test.ts +9 -5
  166. package/src/__tests__/browser-launch.test.ts +26 -15
  167. package/src/__tests__/cdp-client.test.ts +25 -9
  168. package/src/__tests__/close-browser.test.ts +11 -6
  169. package/src/__tests__/console-log.test.ts +36 -13
  170. package/src/__tests__/find.test.ts +58 -20
  171. package/src/__tests__/frame-command.test.ts +12 -6
  172. package/src/__tests__/open-url-navigate-error.test.ts +2 -4
  173. package/src/__tests__/output.test.ts +1 -1
  174. package/src/__tests__/reap-idle-browser.test.ts +276 -0
  175. package/src/__tests__/ref-cache.test.ts +25 -12
  176. package/src/__tests__/session-state.test.ts +40 -28
  177. package/src/__tests__/snapshot.test.ts +60 -21
  178. package/src/__tests__/storage-eval.test.ts +30 -16
  179. package/src/__tests__/tabs.test.ts +26 -10
  180. package/src/browser/action-builder/analyzer.ts +39 -15
  181. package/src/browser/action-builder/types.ts +45 -8
  182. package/src/browser/actions.ts +288 -123
  183. package/src/browser/adapters/gemini.ts +7 -3
  184. package/src/browser/adapters/google.ts +5 -3
  185. package/src/browser/adapters/index.ts +5 -4
  186. package/src/browser/adapters/instagram.ts +4 -2
  187. package/src/browser/adapters/linkedin.ts +4 -2
  188. package/src/browser/adapters/microsoft.ts +9 -5
  189. package/src/browser/adapters/x.ts +7 -3
  190. package/src/browser/browser.ts +188 -42
  191. package/src/browser/cdp.ts +43 -11
  192. package/src/browser/console-log.ts +24 -7
  193. package/src/browser/dashboard/server.ts +44 -25
  194. package/src/browser/dashboard/ui.html +153 -165
  195. package/src/browser/dialog.ts +25 -8
  196. package/src/browser/emulation.ts +86 -36
  197. package/src/browser/find.ts +110 -47
  198. package/src/browser/har.ts +58 -26
  199. package/src/browser/index.ts +16 -16
  200. package/src/browser/network.ts +147 -46
  201. package/src/browser/pdf.ts +4 -4
  202. package/src/browser/profiler.ts +23 -10
  203. package/src/browser/record.ts +38 -19
  204. package/src/browser/ref-cache.ts +38 -17
  205. package/src/browser/screenshot.ts +58 -32
  206. package/src/browser/session.ts +51 -18
  207. package/src/browser/snapshot.ts +34 -20
  208. package/src/browser/storage.ts +73 -17
  209. package/src/browser/tabs.ts +29 -17
  210. package/src/browser/trace.ts +14 -10
  211. package/src/browser/types.ts +23 -4
  212. package/src/browser/vitals.ts +33 -16
  213. package/src/browser/wait.ts +47 -21
  214. package/src/cli/action.ts +52 -21
  215. package/src/cli/commands.ts +1093 -385
  216. package/src/cli/output.ts +5 -5
  217. package/src/cli/platform.ts +44 -23
  218. package/src/cli/types.ts +1 -1
  219. package/src/cli.ts +34 -18
  220. package/src/index.ts +2 -2
@@ -1,23 +1,23 @@
1
- export * from './types.js';
2
- export * from './cdp.js';
3
- export * from './browser.js';
4
- export * from './snapshot.js';
5
1
  export * from './actions.js';
6
- export * from './wait.js';
7
- export * from './network.js';
8
- export * from './screenshot.js';
9
- export * from './session.js';
10
- export * from './tabs.js';
11
- export * from './dialog.js';
2
+ export * from './batch.js';
3
+ export * from './browser.js';
4
+ export * from './cdp.js';
12
5
  export * from './console-log.js';
13
- export * from './storage.js';
6
+ export * from './dialog.js';
7
+ export * from './emulation.js';
14
8
  export * from './find.js';
9
+ export * from './har.js';
10
+ export * from './network.js';
15
11
  export * from './pdf.js';
16
- export * from './emulation.js';
17
- export * from './batch.js';
12
+ export * from './profiler.js';
18
13
  export * from './record.js';
14
+ export * from './ref-cache.js';
15
+ export * from './screenshot.js';
16
+ export * from './session.js';
17
+ export * from './snapshot.js';
18
+ export * from './storage.js';
19
+ export * from './tabs.js';
19
20
  export * from './trace.js';
20
- export * from './profiler.js';
21
+ export * from './types.js';
21
22
  export * from './vitals.js';
22
- export * from './har.js';
23
- export * from './ref-cache.js';
23
+ export * from './wait.js';
@@ -2,7 +2,11 @@ import type { CdpClient } from './cdp.js';
2
2
  import type { CdpCookie, NetworkRoute } from './types.js';
3
3
 
4
4
  export async function getCookies(client: CdpClient, sessionId: string): Promise<CdpCookie[]> {
5
- const result = await client.send<{ cookies: CdpCookie[] }>('Network.getAllCookies', {}, sessionId);
5
+ const result = await client.send<{ cookies: CdpCookie[] }>(
6
+ 'Network.getAllCookies',
7
+ {},
8
+ sessionId,
9
+ );
6
10
  return result.cookies ?? [];
7
11
  }
8
12
 
@@ -12,12 +16,24 @@ export async function getCookies(client: CdpClient, sessionId: string): Promise<
12
16
  * profile. Used for session save/export so we don't leak session tokens for
13
17
  * unrelated domains the user happens to be logged into.
14
18
  */
15
- export async function getCookiesForUrls(client: CdpClient, sessionId: string, urls: string[]): Promise<CdpCookie[]> {
16
- const result = await client.send<{ cookies: CdpCookie[] }>('Network.getCookies', { urls }, sessionId);
19
+ export async function getCookiesForUrls(
20
+ client: CdpClient,
21
+ sessionId: string,
22
+ urls: string[],
23
+ ): Promise<CdpCookie[]> {
24
+ const result = await client.send<{ cookies: CdpCookie[] }>(
25
+ 'Network.getCookies',
26
+ { urls },
27
+ sessionId,
28
+ );
17
29
  return result.cookies ?? [];
18
30
  }
19
31
 
20
- export async function setCookies(client: CdpClient, sessionId: string, cookies: CdpCookie[]): Promise<void> {
32
+ export async function setCookies(
33
+ client: CdpClient,
34
+ sessionId: string,
35
+ cookies: CdpCookie[],
36
+ ): Promise<void> {
21
37
  await client.send('Network.setCookies', { cookies }, sessionId);
22
38
  }
23
39
 
@@ -28,15 +44,19 @@ export async function clearCookies(client: CdpClient, sessionId: string): Promis
28
44
  export async function setExtraHeaders(
29
45
  client: CdpClient,
30
46
  sessionId: string,
31
- headers: Record<string, string>
47
+ headers: Record<string, string>,
32
48
  ): Promise<void> {
33
49
  await client.send('Network.setExtraHTTPHeaders', { headers }, sessionId);
34
50
  }
35
51
 
36
52
  export async function enableInterception(client: CdpClient, sessionId: string): Promise<void> {
37
- await client.send('Fetch.enable', {
38
- patterns: [{ requestStage: 'Request' }],
39
- }, sessionId);
53
+ await client.send(
54
+ 'Fetch.enable',
55
+ {
56
+ patterns: [{ requestStage: 'Request' }],
57
+ },
58
+ sessionId,
59
+ );
40
60
  }
41
61
 
42
62
  const _routeListeners = new Map<string, () => void>();
@@ -44,11 +64,14 @@ const _routeListeners = new Map<string, () => void>();
44
64
  export async function setupRoutes(
45
65
  client: CdpClient,
46
66
  sessionId: string,
47
- routes: NetworkRoute[]
67
+ routes: NetworkRoute[],
48
68
  ): Promise<void> {
49
69
  // Remove previous route listener for this session before registering a new one
50
70
  const prevOff = _routeListeners.get(sessionId);
51
- if (prevOff) { prevOff(); _routeListeners.delete(sessionId); }
71
+ if (prevOff) {
72
+ prevOff();
73
+ _routeListeners.delete(sessionId);
74
+ }
52
75
 
53
76
  if (routes.length === 0) {
54
77
  await client.send('Fetch.disable', {}, sessionId).catch(() => {});
@@ -77,14 +100,21 @@ export async function setupRoutes(
77
100
  await client.send('Fetch.failRequest', { requestId, errorReason: 'Failed' }, sessionId);
78
101
  break;
79
102
  case 'fulfill':
80
- await client.send('Fetch.fulfillRequest', {
81
- requestId,
82
- responseCode: matchedRoute.response?.status ?? 200,
83
- responseHeaders: Object.entries(matchedRoute.response?.headers ?? {}).map(([name, value]) => ({ name, value })),
84
- body: matchedRoute.response?.body ? Buffer.from(matchedRoute.response.body).toString('base64') : '',
85
- }, sessionId);
103
+ await client.send(
104
+ 'Fetch.fulfillRequest',
105
+ {
106
+ requestId,
107
+ responseCode: matchedRoute.response?.status ?? 200,
108
+ responseHeaders: Object.entries(matchedRoute.response?.headers ?? {}).map(
109
+ ([name, value]) => ({ name, value }),
110
+ ),
111
+ body: matchedRoute.response?.body
112
+ ? Buffer.from(matchedRoute.response.body).toString('base64')
113
+ : '',
114
+ },
115
+ sessionId,
116
+ );
86
117
  break;
87
- case 'continue':
88
118
  default:
89
119
  await client.send('Fetch.continueRequest', { requestId }, sessionId);
90
120
  break;
@@ -96,15 +126,29 @@ export async function setupRoutes(
96
126
  });
97
127
  _routeListeners.set(sessionId, off);
98
128
 
99
- await client.send('Fetch.enable', {
100
- patterns: routes.map((r) => ({ urlPattern: globToFetchPattern(r.pattern), requestStage: 'Request' })),
101
- }, sessionId);
129
+ await client.send(
130
+ 'Fetch.enable',
131
+ {
132
+ patterns: routes.map((r) => ({
133
+ urlPattern: globToFetchPattern(r.pattern),
134
+ requestStage: 'Request',
135
+ })),
136
+ },
137
+ sessionId,
138
+ );
102
139
  }
103
140
 
104
141
  type CapturedRequest = {
105
- id: string; url: string; method: string; status?: number; mimeType?: string;
106
- requestHeaders?: Record<string, string>; responseHeaders?: Record<string, string>;
107
- startTime: number; endTime?: number; encodedSize?: number;
142
+ id: string;
143
+ url: string;
144
+ method: string;
145
+ status?: number;
146
+ mimeType?: string;
147
+ requestHeaders?: Record<string, string>;
148
+ responseHeaders?: Record<string, string>;
149
+ startTime: number;
150
+ endTime?: number;
151
+ encodedSize?: number;
108
152
  };
109
153
 
110
154
  const _capturedRequests = new Map<string, Map<string, CapturedRequest>>();
@@ -121,29 +165,53 @@ export function startRequestCapture(client: CdpClient, sessionId: string): void
121
165
 
122
166
  const offReq = client.on('Network.requestWillBeSent', (params, sid) => {
123
167
  if (sid !== sessionId) return;
124
- const p = params as { requestId: string; request: { url: string; method: string; headers: Record<string, string> }; timestamp: number };
125
- idx().set(p.requestId, { id: p.requestId, url: p.request.url, method: p.request.method, requestHeaders: p.request.headers, startTime: p.timestamp * 1000 });
168
+ const p = params as {
169
+ requestId: string;
170
+ request: { url: string; method: string; headers: Record<string, string> };
171
+ timestamp: number;
172
+ };
173
+ idx().set(p.requestId, {
174
+ id: p.requestId,
175
+ url: p.request.url,
176
+ method: p.request.method,
177
+ requestHeaders: p.request.headers,
178
+ startTime: p.timestamp * 1000,
179
+ });
126
180
  });
127
181
 
128
182
  const offResp = client.on('Network.responseReceived', (params, sid) => {
129
183
  if (sid !== sessionId) return;
130
- const p = params as { requestId: string; response: { status: number; mimeType: string; headers: Record<string, string> }; timestamp: number };
184
+ const p = params as {
185
+ requestId: string;
186
+ response: { status: number; mimeType: string; headers: Record<string, string> };
187
+ timestamp: number;
188
+ };
131
189
  const entry = idx().get(p.requestId);
132
- if (entry) { entry.status = p.response.status; entry.mimeType = p.response.mimeType; entry.responseHeaders = p.response.headers; entry.endTime = p.timestamp * 1000; }
190
+ if (entry) {
191
+ entry.status = p.response.status;
192
+ entry.mimeType = p.response.mimeType;
193
+ entry.responseHeaders = p.response.headers;
194
+ entry.endTime = p.timestamp * 1000;
195
+ }
133
196
  });
134
197
 
135
198
  const offFinished = client.on('Network.loadingFinished', (params, sid) => {
136
199
  if (sid !== sessionId) return;
137
200
  const p = params as { requestId: string; encodedDataLength: number; timestamp: number };
138
201
  const entry = idx().get(p.requestId);
139
- if (entry) { entry.encodedSize = p.encodedDataLength; entry.endTime = p.timestamp * 1000; }
202
+ if (entry) {
203
+ entry.encodedSize = p.encodedDataLength;
204
+ entry.endTime = p.timestamp * 1000;
205
+ }
140
206
  });
141
207
 
142
208
  const offFailed = client.on('Network.loadingFailed', (params, sid) => {
143
209
  if (sid !== sessionId) return;
144
210
  const p = params as { requestId: string; timestamp: number };
145
211
  const entry = idx().get(p.requestId);
146
- if (entry) { entry.endTime = p.timestamp * 1000; }
212
+ if (entry) {
213
+ entry.endTime = p.timestamp * 1000;
214
+ }
147
215
  });
148
216
 
149
217
  _captureListeners.set(sessionId, [offReq, offResp, offFinished, offFailed]);
@@ -151,7 +219,10 @@ export function startRequestCapture(client: CdpClient, sessionId: string): void
151
219
 
152
220
  export function stopRequestCapture(sessionId: string): void {
153
221
  const offs = _captureListeners.get(sessionId);
154
- if (offs) { for (const off of offs) off(); _captureListeners.delete(sessionId); }
222
+ if (offs) {
223
+ for (const off of offs) off();
224
+ _captureListeners.delete(sessionId);
225
+ }
155
226
  _capturedRequests.delete(sessionId);
156
227
  }
157
228
 
@@ -165,20 +236,36 @@ export function clearCapturedRequests(sessionId: string): void {
165
236
 
166
237
  export async function disableInterception(client: CdpClient, sessionId: string): Promise<void> {
167
238
  const prevOff = _routeListeners.get(sessionId);
168
- if (prevOff) { prevOff(); _routeListeners.delete(sessionId); }
239
+ if (prevOff) {
240
+ prevOff();
241
+ _routeListeners.delete(sessionId);
242
+ }
169
243
  await client.send('Fetch.disable', {}, sessionId);
170
244
  }
171
245
 
172
246
  export function teardownRouteInterception(sessionId: string): void {
173
247
  const prevOff = _routeListeners.get(sessionId);
174
- if (prevOff) { prevOff(); _routeListeners.delete(sessionId); }
248
+ if (prevOff) {
249
+ prevOff();
250
+ _routeListeners.delete(sessionId);
251
+ }
175
252
  }
176
253
 
177
- export async function getLocalStorage(client: CdpClient, sessionId: string): Promise<Record<string, string>> {
178
- const result = await client.send<{ result: { value?: string }; exceptionDetails?: { text: string; exception?: { description?: string } } }>('Runtime.evaluate', {
179
- expression: 'JSON.stringify(Object.fromEntries(Object.entries(localStorage)))',
180
- returnByValue: true,
181
- }, sessionId);
254
+ export async function getLocalStorage(
255
+ client: CdpClient,
256
+ sessionId: string,
257
+ ): Promise<Record<string, string>> {
258
+ const result = await client.send<{
259
+ result: { value?: string };
260
+ exceptionDetails?: { text: string; exception?: { description?: string } };
261
+ }>(
262
+ 'Runtime.evaluate',
263
+ {
264
+ expression: 'JSON.stringify(Object.fromEntries(Object.entries(localStorage)))',
265
+ returnByValue: true,
266
+ },
267
+ sessionId,
268
+ );
182
269
  if (result.exceptionDetails) return {};
183
270
  try {
184
271
  return JSON.parse(result.result?.value ?? '{}');
@@ -190,7 +277,7 @@ export async function getLocalStorage(client: CdpClient, sessionId: string): Pro
190
277
  export async function setLocalStorage(
191
278
  client: CdpClient,
192
279
  sessionId: string,
193
- data: Record<string, string>
280
+ data: Record<string, string>,
194
281
  ): Promise<void> {
195
282
  const script = Object.entries(data)
196
283
  .map(([k, v]) => `localStorage.setItem(${JSON.stringify(k)}, ${JSON.stringify(v)})`)
@@ -201,16 +288,28 @@ export async function setLocalStorage(
201
288
  exceptionDetails?: { text: string; exception?: { description?: string } };
202
289
  }>('Runtime.evaluate', { expression: script, returnByValue: true }, sessionId);
203
290
  if (result.exceptionDetails) {
204
- throw new Error(`setLocalStorage failed: ${result.exceptionDetails.exception?.description ?? result.exceptionDetails.text}`);
291
+ throw new Error(
292
+ `setLocalStorage failed: ${result.exceptionDetails.exception?.description ?? result.exceptionDetails.text}`,
293
+ );
205
294
  }
206
295
  }
207
296
  }
208
297
 
209
- export async function getSessionStorage(client: CdpClient, sessionId: string): Promise<Record<string, string>> {
210
- const result = await client.send<{ result: { value?: string }; exceptionDetails?: { text: string; exception?: { description?: string } } }>('Runtime.evaluate', {
211
- expression: 'JSON.stringify(Object.fromEntries(Object.entries(sessionStorage)))',
212
- returnByValue: true,
213
- }, sessionId);
298
+ export async function getSessionStorage(
299
+ client: CdpClient,
300
+ sessionId: string,
301
+ ): Promise<Record<string, string>> {
302
+ const result = await client.send<{
303
+ result: { value?: string };
304
+ exceptionDetails?: { text: string; exception?: { description?: string } };
305
+ }>(
306
+ 'Runtime.evaluate',
307
+ {
308
+ expression: 'JSON.stringify(Object.fromEntries(Object.entries(sessionStorage)))',
309
+ returnByValue: true,
310
+ },
311
+ sessionId,
312
+ );
214
313
  if (result.exceptionDetails) return {};
215
314
  try {
216
315
  return JSON.parse(result.result?.value ?? '{}');
@@ -222,7 +321,7 @@ export async function getSessionStorage(client: CdpClient, sessionId: string): P
222
321
  export async function setSessionStorage(
223
322
  client: CdpClient,
224
323
  sessionId: string,
225
- data: Record<string, string>
324
+ data: Record<string, string>,
226
325
  ): Promise<void> {
227
326
  const script = Object.entries(data)
228
327
  .map(([k, v]) => `sessionStorage.setItem(${JSON.stringify(k)}, ${JSON.stringify(v)})`)
@@ -233,7 +332,9 @@ export async function setSessionStorage(
233
332
  exceptionDetails?: { text: string; exception?: { description?: string } };
234
333
  }>('Runtime.evaluate', { expression: script, returnByValue: true }, sessionId);
235
334
  if (result.exceptionDetails) {
236
- throw new Error(`setSessionStorage failed: ${result.exceptionDetails.exception?.description ?? result.exceptionDetails.text}`);
335
+ throw new Error(
336
+ `setSessionStorage failed: ${result.exceptionDetails.exception?.description ?? result.exceptionDetails.text}`,
337
+ );
237
338
  }
238
339
  }
239
340
  }
@@ -1,7 +1,7 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
1
4
  import type { CdpClient } from './cdp.js';
2
- import { writeFile } from 'fs/promises';
3
- import { join } from 'path';
4
- import { tmpdir } from 'os';
5
5
 
6
6
  export interface PdfOptions {
7
7
  path?: string;
@@ -19,7 +19,7 @@ export interface PdfOptions {
19
19
  export async function capturePdf(
20
20
  client: CdpClient,
21
21
  sessionId: string,
22
- options: PdfOptions = {}
22
+ options: PdfOptions = {},
23
23
  ): Promise<string> {
24
24
  const params: Record<string, unknown> = {
25
25
  landscape: options.landscape ?? false,
@@ -1,7 +1,7 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
1
4
  import type { CdpClient } from './cdp.js';
2
- import { writeFile } from 'fs/promises';
3
- import { join } from 'path';
4
- import { tmpdir } from 'os';
5
5
 
6
6
  export interface ProfilerOptions {
7
7
  path?: string;
@@ -14,14 +14,18 @@ const _heapSessions = new Set<string>();
14
14
  export async function startCpuProfile(
15
15
  client: CdpClient,
16
16
  sessionId: string,
17
- options: ProfilerOptions = {}
17
+ options: ProfilerOptions = {},
18
18
  ): Promise<void> {
19
19
  if (_sessions.has(sessionId)) {
20
20
  throw new Error('CPU profiler already running for this session');
21
21
  }
22
22
  await client.send('Profiler.enable', {}, sessionId);
23
23
  if (options.samplingInterval !== undefined) {
24
- await client.send('Profiler.setSamplingInterval', { interval: options.samplingInterval }, sessionId);
24
+ await client.send(
25
+ 'Profiler.setSamplingInterval',
26
+ { interval: options.samplingInterval },
27
+ sessionId,
28
+ );
25
29
  }
26
30
  await client.send('Profiler.start', {}, sessionId);
27
31
  _sessions.add(sessionId);
@@ -30,7 +34,7 @@ export async function startCpuProfile(
30
34
  export async function stopCpuProfile(
31
35
  client: CdpClient,
32
36
  sessionId: string,
33
- outputPath?: string
37
+ outputPath?: string,
34
38
  ): Promise<string> {
35
39
  if (!_sessions.has(sessionId)) {
36
40
  throw new Error('No active CPU profiler for this session');
@@ -57,7 +61,7 @@ export function isProfilingActive(sessionId: string): boolean {
57
61
  export async function startHeapSnapshot(
58
62
  client: CdpClient,
59
63
  sessionId: string,
60
- outputPath?: string
64
+ outputPath?: string,
61
65
  ): Promise<string> {
62
66
  if (_heapSessions.has(sessionId)) {
63
67
  throw new Error('Heap snapshot already in progress for this session');
@@ -79,10 +83,19 @@ export async function startHeapSnapshot(
79
83
  }, 120_000);
80
84
  const off2 = client.on('HeapProfiler.reportHeapSnapshotProgress', (params, sid) => {
81
85
  if (sid !== sessionId) return;
82
- if (params.finished) { clearTimeout(timeoutHandle); off2(); resolve(); }
86
+ if (params.finished) {
87
+ clearTimeout(timeoutHandle);
88
+ off2();
89
+ resolve();
90
+ }
83
91
  });
84
- client.send('HeapProfiler.takeHeapSnapshot', { reportProgress: true }, sessionId)
85
- .catch((err) => { clearTimeout(timeoutHandle); off2(); reject(err); });
92
+ client
93
+ .send('HeapProfiler.takeHeapSnapshot', { reportProgress: true }, sessionId)
94
+ .catch((err) => {
95
+ clearTimeout(timeoutHandle);
96
+ off2();
97
+ reject(err);
98
+ });
86
99
  });
87
100
  } finally {
88
101
  off();
@@ -1,7 +1,7 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
1
4
  import type { CdpClient } from './cdp.js';
2
- import { writeFile } from 'fs/promises';
3
- import { join } from 'path';
4
- import { tmpdir } from 'os';
5
5
 
6
6
  export interface RecordOptions {
7
7
  path?: string;
@@ -34,7 +34,7 @@ const _sessions = new Map<string, RecordingState>();
34
34
  export async function startRecording(
35
35
  client: CdpClient,
36
36
  sessionId: string,
37
- options: RecordOptions = {}
37
+ options: RecordOptions = {},
38
38
  ): Promise<void> {
39
39
  const existing = _sessions.get(sessionId);
40
40
  if (existing && !existing.autoStopped) {
@@ -48,7 +48,12 @@ export async function startRecording(
48
48
  _sessions.delete(sessionId);
49
49
  }
50
50
 
51
- const state: RecordingState = { frames: [], offScreencast: null, totalBytes: 0, autoStopped: false };
51
+ const state: RecordingState = {
52
+ frames: [],
53
+ offScreencast: null,
54
+ totalBytes: 0,
55
+ autoStopped: false,
56
+ };
52
57
  _sessions.set(sessionId, state);
53
58
 
54
59
  state.offScreencast = client.on('Page.screencastFrame', async (params, sid) => {
@@ -63,22 +68,28 @@ export async function startRecording(
63
68
  // eslint-disable-next-line no-console
64
69
  console.error(
65
70
  `[monobrowse] Screen recording auto-stopped: reached ${Math.round(MAX_SCREENCAST_BYTES / (1024 * 1024))}MB ` +
66
- `of buffered frame data (${state.frames.length} frames). Call "record stop" to save what was captured.`
71
+ `of buffered frame data (${state.frames.length} frames). Call "record stop" to save what was captured.`,
67
72
  );
68
73
  await client.send('Page.stopScreencast', {}, sessionId).catch(() => {});
69
74
  }
70
75
  }
71
- await client.send('Page.screencastFrameAck', { sessionId: frameSessionId }, sessionId).catch(() => {});
76
+ await client
77
+ .send('Page.screencastFrameAck', { sessionId: frameSessionId }, sessionId)
78
+ .catch(() => {});
72
79
  });
73
80
 
74
81
  try {
75
- await client.send('Page.startScreencast', {
76
- format: options.format ?? 'jpeg',
77
- quality: options.quality ?? 80,
78
- everyNthFrame: options.everyNthFrame ?? 1,
79
- ...(options.maxWidth ? { maxWidth: options.maxWidth } : {}),
80
- ...(options.maxHeight ? { maxHeight: options.maxHeight } : {}),
81
- }, sessionId);
82
+ await client.send(
83
+ 'Page.startScreencast',
84
+ {
85
+ format: options.format ?? 'jpeg',
86
+ quality: options.quality ?? 80,
87
+ everyNthFrame: options.everyNthFrame ?? 1,
88
+ ...(options.maxWidth ? { maxWidth: options.maxWidth } : {}),
89
+ ...(options.maxHeight ? { maxHeight: options.maxHeight } : {}),
90
+ },
91
+ sessionId,
92
+ );
82
93
  } catch (err) {
83
94
  state.offScreencast?.();
84
95
  _sessions.delete(sessionId);
@@ -89,7 +100,7 @@ export async function startRecording(
89
100
  export async function stopRecording(
90
101
  client: CdpClient,
91
102
  sessionId: string,
92
- outputPath?: string
103
+ outputPath?: string,
93
104
  ): Promise<string> {
94
105
  const state = _sessions.get(sessionId);
95
106
  if (!state) throw new Error('No active recording for this session');
@@ -110,16 +121,24 @@ export async function stopRecording(
110
121
  return path;
111
122
  }
112
123
 
113
- export function getRecordingStatus(sessionId: string): { recording: boolean; frames: number; autoStopped: boolean } {
124
+ export function getRecordingStatus(sessionId: string): {
125
+ recording: boolean;
126
+ frames: number;
127
+ autoStopped: boolean;
128
+ } {
114
129
  const state = _sessions.get(sessionId);
115
- return { recording: !!state && !state.autoStopped, frames: state?.frames.length ?? 0, autoStopped: state?.autoStopped ?? false };
130
+ return {
131
+ recording: !!state && !state.autoStopped,
132
+ frames: state?.frames.length ?? 0,
133
+ autoStopped: state?.autoStopped ?? false,
134
+ };
116
135
  }
117
136
 
118
137
  export async function saveFrameAsPng(
119
- client: CdpClient,
138
+ _client: CdpClient,
120
139
  sessionId: string,
121
140
  frameIndex: number,
122
- outputPath: string
141
+ outputPath: string,
123
142
  ): Promise<void> {
124
143
  const state = _sessions.get(sessionId);
125
144
  if (!state || frameIndex >= state.frames.length) {
@@ -10,8 +10,8 @@
10
10
  * The full AX-tree text/dump is intentionally NOT persisted — only the
11
11
  * per-ref index, to keep the file small.
12
12
  */
13
- import { readFile, writeFile, mkdir, rm } from 'fs/promises';
14
- import { join } from 'path';
13
+ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
14
+ import { join } from 'node:path';
15
15
  import type { ElementRef } from './types.js';
16
16
 
17
17
  const CACHE_DIR = join(process.cwd(), '.monomind', 'monobrowse');
@@ -40,7 +40,7 @@ export interface RefCacheEntry {
40
40
  export async function saveRefCache(
41
41
  targetId: string,
42
42
  url: string,
43
- refs: Map<string, ElementRef>
43
+ refs: Map<string, ElementRef>,
44
44
  ): Promise<void> {
45
45
  try {
46
46
  await mkdir(CACHE_DIR, { recursive: true });
@@ -99,7 +99,7 @@ export async function clearRefCache(): Promise<void> {
99
99
  */
100
100
  export async function saveActivePort(
101
101
  port: number,
102
- opts?: { launched?: boolean; pid?: number; userDataDir?: string }
102
+ opts?: { launched?: boolean; pid?: number; userDataDir?: string },
103
103
  ): Promise<void> {
104
104
  try {
105
105
  await mkdir(CACHE_DIR, { recursive: true });
@@ -113,13 +113,16 @@ export async function saveActivePort(
113
113
  // and kill the Chrome this one launched. Without this, closeBrowser()'s
114
114
  // PID-kill fallback can never fire outside the launching process, since
115
115
  // the in-memory launchedPids Map (browser.ts) is empty there.
116
- await writeFile(PORT_FILE, JSON.stringify({
117
- port,
118
- launched: opts?.launched !== false,
119
- pid: opts?.pid,
120
- userDataDir: opts?.userDataDir,
121
- savedAt: Date.now(),
122
- }));
116
+ await writeFile(
117
+ PORT_FILE,
118
+ JSON.stringify({
119
+ port,
120
+ launched: opts?.launched !== false,
121
+ pid: opts?.pid,
122
+ userDataDir: opts?.userDataDir,
123
+ savedAt: Date.now(),
124
+ }),
125
+ );
123
126
  } catch {
124
127
  // Best-effort — persistence failure just means the next process falls
125
128
  // back to the hardcoded default port, matching prior behavior.
@@ -142,17 +145,35 @@ export async function loadActivePort(): Promise<number | null> {
142
145
  }
143
146
 
144
147
  /** Load the persisted active port with its provenance flag, PID, user-data-dir, and save timestamp. */
145
- export async function loadActivePortInfo(): Promise<
146
- { port: number; launched: boolean; pid?: number; userDataDir?: string; savedAt?: number } | null
147
- > {
148
+ export async function loadActivePortInfo(): Promise<{
149
+ port: number;
150
+ launched: boolean;
151
+ pid?: number;
152
+ userDataDir?: string;
153
+ savedAt?: number;
154
+ } | null> {
148
155
  try {
149
156
  const raw = await readFile(PORT_FILE, 'utf8');
150
- const data = JSON.parse(raw) as { port?: unknown; launched?: unknown; pid?: unknown; userDataDir?: unknown; savedAt?: unknown };
151
- if (typeof data.port === 'number' && Number.isInteger(data.port) && data.port >= 1024 && data.port <= 65535) {
157
+ const data = JSON.parse(raw) as {
158
+ port?: unknown;
159
+ launched?: unknown;
160
+ pid?: unknown;
161
+ userDataDir?: unknown;
162
+ savedAt?: unknown;
163
+ };
164
+ if (
165
+ typeof data.port === 'number' &&
166
+ Number.isInteger(data.port) &&
167
+ data.port >= 1024 &&
168
+ data.port <= 65535
169
+ ) {
152
170
  return {
153
171
  port: data.port,
154
172
  launched: data.launched !== false,
155
- pid: typeof data.pid === 'number' && Number.isInteger(data.pid) && data.pid > 0 ? data.pid : undefined,
173
+ pid:
174
+ typeof data.pid === 'number' && Number.isInteger(data.pid) && data.pid > 0
175
+ ? data.pid
176
+ : undefined,
156
177
  userDataDir: typeof data.userDataDir === 'string' ? data.userDataDir : undefined,
157
178
  savedAt: typeof data.savedAt === 'number' ? data.savedAt : undefined,
158
179
  };