@presto1314w/vite-devtools-browser 0.1.3 → 0.1.4

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.
package/README.md CHANGED
@@ -1,14 +1,20 @@
1
1
  # vite-browser
2
2
 
3
- Agent Skill for AI coding assistants to debug Vite applications with structured access to Vue/React/Svelte runtime state. The CLI is the supporting runtime used by the skill for component trees, store/router inspection, logs, network traces, screenshots, and scripted page evaluation.
3
+ `vite-browser` is a debugging toolchain for Vite apps:
4
+ - Agent Skill: scenario-based debugging workflows for coding assistants
5
+ - CLI Runtime (`@presto1314w/vite-devtools-browser`): structured inspection of Vue/React/Svelte runtime state
4
6
 
5
- ## Skills
7
+ Current documented baseline: `v0.1.4`.
8
+
9
+ ## Install
10
+
11
+ ### Install Skill
6
12
 
7
13
  ```bash
8
14
  npx skills add MapleCity1314/vite-browser
9
15
  ```
10
16
 
11
- ## CLI Installation (Optional)
17
+ ### Install CLI
12
18
 
13
19
  ```bash
14
20
  npm install -g @presto1314w/vite-devtools-browser
@@ -18,100 +24,111 @@ npx playwright install chromium
18
24
  ## Quick Start
19
25
 
20
26
  ```bash
21
- # Start your Vite dev server
22
- cd my-vue-app
27
+ # terminal A: start Vite app
28
+ cd my-app
23
29
  npm run dev
24
30
 
25
- # In another terminal
31
+ # terminal B: inspect runtime
26
32
  vite-browser open http://localhost:5173
27
- vite-browser detect # vue@3.5.29 / react@19.x / svelte@x
28
- vite-browser vue tree # Vue component tree
29
- vite-browser react tree # React component tree
30
- vite-browser svelte tree # Svelte component tree (best effort)
31
- vite-browser screenshot # Take screenshot
32
- vite-browser logs # Console logs
33
- vite-browser network # Network requests
33
+ vite-browser detect
34
+ vite-browser vue tree
35
+ vite-browser vue pinia
36
+ vite-browser vite runtime
37
+ vite-browser vite hmr trace --limit 20
38
+ vite-browser vite module-graph trace --limit 50
39
+ vite-browser errors --mapped --inline-source
40
+ vite-browser network
34
41
  vite-browser close
35
42
  ```
36
43
 
37
- ## Features
44
+ ## Core Capabilities
38
45
 
39
- - Framework Detection: Auto-detect Vue, React, Svelte and versions (best effort)
40
- - Vue DevTools: Component tree, props, state, computed properties, source locations
41
- - React DevTools: Component tree + component inspection (props/hooks/state/context)
42
- - Svelte Support: Component tree + component detail inspection when runtime metadata is available
43
- - Pinia Integration: Inspect store state and getters
44
- - Vue Router: Current route, params, query, all routes
45
- - Network Monitoring: Track requests, headers, bodies, and response payloads
46
- - Console Logs: Capture console.log, warn, error, debug
47
- - Screenshots: Full-page PNG screenshots
48
- - JavaScript Evaluation: Run arbitrary JS in page context
49
- - Vite Integration: Error tracking, HMR monitoring
46
+ - Framework detection: Vue/React/Svelte best-effort detection and version hinting
47
+ - Vue runtime inspection: component tree/details, Pinia stores/getters, Vue Router state
48
+ - React runtime inspection: component tree/details (props/state/hooks/context/source)
49
+ - Svelte runtime inspection: component tree/details when metadata is available
50
+ - Vite runtime diagnostics:
51
+ - runtime status summary
52
+ - HMR summary/timeline/clear
53
+ - module-graph snapshot/diff/clear
54
+ - source-mapped errors with optional inline source snippet
55
+ - Debug utilities: console logs, network tracing, screenshot, page `eval`
50
56
 
51
- ## Commands
57
+ ## Command Reference
52
58
 
53
- ### Browser Control
54
- ```bash
55
- vite-browser open <url> # Launch browser and navigate
56
- vite-browser close # Close browser and daemon
57
- vite-browser goto <url> # Navigate to URL
58
- vite-browser back # Go back
59
- vite-browser reload # Reload page
60
- ```
59
+ ### Browser
61
60
 
62
- ### Framework Detection
63
61
  ```bash
64
- vite-browser detect # Detect framework and version
62
+ vite-browser open <url> [--cookies-json <file>]
63
+ vite-browser close
64
+ vite-browser goto <url>
65
+ vite-browser back
66
+ vite-browser reload
65
67
  ```
66
68
 
67
- ### Vue DevTools
68
- ```bash
69
- vite-browser vue tree # Show component tree
70
- vite-browser vue tree <id> # Inspect component details
71
- vite-browser vue pinia # List all Pinia stores
72
- vite-browser vue pinia <store> # Inspect specific store
73
- vite-browser vue router # Show router information
74
- ```
69
+ ### Framework
75
70
 
76
- ### React DevTools
77
71
  ```bash
78
- vite-browser react tree # Show React component tree
79
- vite-browser react tree <id> # Inspect props/hooks/state/context/source
72
+ vite-browser detect
73
+ vite-browser vue tree [id]
74
+ vite-browser vue pinia [store]
75
+ vite-browser vue router
76
+ vite-browser react tree [id]
77
+ vite-browser svelte tree [id]
80
78
  ```
81
79
 
82
- ### Svelte
80
+ ### Vite Runtime
81
+
83
82
  ```bash
84
- vite-browser svelte tree # Show Svelte component tree
85
- vite-browser svelte tree <id> # Inspect Svelte component details
83
+ vite-browser vite restart
84
+ vite-browser vite runtime
85
+ vite-browser vite hmr
86
+ vite-browser vite hmr trace [--limit <n>]
87
+ vite-browser vite hmr clear
88
+ vite-browser vite module-graph [--filter <txt>] [--limit <n>]
89
+ vite-browser vite module-graph trace [--filter <txt>] [--limit <n>]
90
+ vite-browser vite module-graph clear
91
+ vite-browser errors
92
+ vite-browser errors --mapped
93
+ vite-browser errors --mapped --inline-source
86
94
  ```
87
95
 
88
- ### Debugging
96
+ ### Utilities
97
+
89
98
  ```bash
90
- vite-browser screenshot # Take full-page screenshot
91
- vite-browser eval <script> # Run JavaScript in page
92
- vite-browser logs # Show console logs
93
- vite-browser errors # Show Vite errors
94
- vite-browser network # List network requests
95
- vite-browser network <idx> # Inspect specific request
99
+ vite-browser logs
100
+ vite-browser network [idx]
101
+ vite-browser screenshot
102
+ vite-browser eval <script>
96
103
  ```
97
104
 
98
- ## Architecture
105
+ ## Skill Packs
99
106
 
100
- - Daemon + Socket: Background process with socket communication
101
- - Playwright: Headed Chromium browser
102
- - One Browser, One Page: Single persistent browser instance
103
- - Auto-start: Daemon starts automatically on first command
107
+ The entry skill routes to specialized workflows:
104
108
 
105
- ## Requirements
109
+ - `skills/vite-browser-core-debug/SKILL.md`
110
+ - `skills/vite-browser-runtime-diagnostics/SKILL.md`
111
+ - `skills/vite-browser-network-regression/SKILL.md`
112
+ - `skills/vite-browser-release-smoke/SKILL.md`
106
113
 
107
- - Node.js 20+
108
- - Chromium (via Playwright)
109
- - Vite dev server running
110
- - Vue/React/Svelte app for framework-specific commands
114
+ Router definition: [skills/SKILL.md](./skills/SKILL.md)
111
115
 
112
- ## Documentation
116
+ ## Local Development
117
+
118
+ ```bash
119
+ pnpm install
120
+ pnpm build
121
+ pnpm test
122
+ pnpm test:coverage
123
+ pnpm test:evals
124
+ pnpm test:evals:e2e
125
+ ```
126
+
127
+ ## Requirements
113
128
 
114
- See [SKILL.md](./skills/SKILL.md) for complete command reference and usage examples.
129
+ - Node.js `>=20`
130
+ - Chromium installed via Playwright
131
+ - Running Vite dev server
115
132
 
116
133
  ## License
117
134
 
package/dist/browser.d.ts CHANGED
@@ -1,9 +1,40 @@
1
+ import { type BrowserContext } from "playwright";
2
+ import { resolveViaSourceMap } from "./sourcemap.js";
3
+ type HmrEventType = "connecting" | "connected" | "update" | "full-reload" | "error" | "log";
4
+ export type HmrEvent = {
5
+ timestamp: number;
6
+ type: HmrEventType;
7
+ message: string;
8
+ path?: string;
9
+ };
10
+ export type RuntimeSnapshot = {
11
+ url: string;
12
+ hasViteClient: boolean;
13
+ wsState: string;
14
+ hasErrorOverlay: boolean;
15
+ timestamp: number;
16
+ };
17
+ export type ModuleRow = {
18
+ url: string;
19
+ initiator: string;
20
+ durationMs: number;
21
+ };
22
+ export type ModuleGraphMode = "snapshot" | "trace" | "clear";
1
23
  export declare function open(url: string | undefined): Promise<void>;
2
24
  export declare function cookies(cookies: {
3
25
  name: string;
4
26
  value: string;
5
27
  }[], domain: string): Promise<number>;
6
28
  export declare function close(): Promise<void>;
29
+ export declare function contextUsable(current: Pick<BrowserContext, "pages"> | null): current is Pick<BrowserContext, "pages">;
30
+ export declare function isClosedTargetError(error: unknown): boolean;
31
+ export declare function recordConsoleMessage(logs: string[], events: HmrEvent[], type: string, message: string, maxLogs?: number, maxEvents?: number): void;
32
+ export declare function parseViteLog(message: string): HmrEvent;
33
+ export declare function normalizeLimit(limit: number, fallback: number, max: number): number;
34
+ export declare function formatRuntimeStatus(runtime: RuntimeSnapshot, currentFramework: string, events: HmrEvent[]): string;
35
+ export declare function formatHmrTrace(mode: "summary" | "trace", events: HmrEvent[], limit: number): string;
36
+ export declare function formatModuleGraphSnapshot(rows: ModuleRow[], filter?: string, limit?: number): string;
37
+ export declare function formatModuleGraphTrace(currentUrls: string[], previousUrls: Set<string> | null, filter?: string, limit?: number): string;
7
38
  export declare function goto(url: string): Promise<string>;
8
39
  export declare function back(): Promise<void>;
9
40
  export declare function reload(): Promise<string>;
@@ -17,9 +48,11 @@ export declare function viteRestart(): Promise<string>;
17
48
  export declare function viteHMR(): Promise<string>;
18
49
  export declare function viteRuntimeStatus(): Promise<string>;
19
50
  export declare function viteHMRTrace(mode: "summary" | "trace" | "clear", limit?: number): Promise<string>;
20
- export declare function viteModuleGraph(filter?: string, limit?: number, mode?: "snapshot" | "trace" | "clear"): Promise<string>;
51
+ export declare function viteModuleGraph(filter?: string, limit?: number, mode?: ModuleGraphMode): Promise<string>;
21
52
  export declare function errors(mapped?: boolean, inlineSource?: boolean): Promise<string>;
22
53
  export declare function logs(): Promise<string>;
23
54
  export declare function screenshot(): Promise<string>;
24
55
  export declare function evaluate(script: string): Promise<string>;
25
56
  export declare function network(idx?: number): Promise<string>;
57
+ export declare function mapStackTrace(stack: string, origin: string, inlineSource?: boolean, resolver?: typeof resolveViaSourceMap): Promise<string>;
58
+ export {};
package/dist/browser.js CHANGED
@@ -71,7 +71,7 @@ async function ensurePage() {
71
71
  }
72
72
  return page;
73
73
  }
74
- function contextUsable(current) {
74
+ export function contextUsable(current) {
75
75
  if (!current)
76
76
  return false;
77
77
  try {
@@ -82,7 +82,7 @@ function contextUsable(current) {
82
82
  return false;
83
83
  }
84
84
  }
85
- function isClosedTargetError(error) {
85
+ export function isClosedTargetError(error) {
86
86
  if (!(error instanceof Error))
87
87
  return false;
88
88
  return /Target page, context or browser has been closed/i.test(error.message);
@@ -115,20 +115,22 @@ async function launch() {
115
115
  }
116
116
  function attachListeners(currentPage) {
117
117
  currentPage.on("console", (msg) => {
118
- const text = `[${msg.type()}] ${msg.text()}`;
119
- consoleLogs.push(text);
120
- if (consoleLogs.length > MAX_LOGS)
121
- consoleLogs.shift();
122
- const viteMessage = msg.text();
123
- if (!viteMessage.includes("[vite]"))
124
- return;
125
- const event = parseViteLog(viteMessage);
126
- hmrEvents.push(event);
127
- if (hmrEvents.length > MAX_HMR_EVENTS)
128
- hmrEvents.shift();
118
+ recordConsoleMessage(consoleLogs, hmrEvents, msg.type(), msg.text());
129
119
  });
130
120
  }
131
- function parseViteLog(message) {
121
+ export function recordConsoleMessage(logs, events, type, message, maxLogs = MAX_LOGS, maxEvents = MAX_HMR_EVENTS) {
122
+ const text = `[${type}] ${message}`;
123
+ logs.push(text);
124
+ if (logs.length > maxLogs)
125
+ logs.shift();
126
+ if (!message.includes("[vite]"))
127
+ return;
128
+ const event = parseViteLog(message);
129
+ events.push(event);
130
+ if (events.length > maxEvents)
131
+ events.shift();
132
+ }
133
+ export function parseViteLog(message) {
132
134
  const lower = message.toLowerCase();
133
135
  const event = {
134
136
  timestamp: Date.now(),
@@ -154,6 +156,103 @@ function parseViteLog(message) {
154
156
  event.path = hotUpdateMatch[1].trim();
155
157
  return event;
156
158
  }
159
+ export function normalizeLimit(limit, fallback, max) {
160
+ if (!Number.isFinite(limit) || limit <= 0)
161
+ return fallback;
162
+ return Math.min(limit, max);
163
+ }
164
+ export function formatRuntimeStatus(runtime, currentFramework, events) {
165
+ const output = [];
166
+ output.push("# Vite Runtime");
167
+ output.push(`URL: ${runtime.url}`);
168
+ output.push(`Framework: ${currentFramework}`);
169
+ output.push(`Vite Client: ${runtime.hasViteClient ? "loaded" : "not detected"}`);
170
+ output.push(`HMR Socket: ${runtime.wsState}`);
171
+ output.push(`Error Overlay: ${runtime.hasErrorOverlay ? "present" : "none"}`);
172
+ output.push(`Tracked HMR Events: ${events.length}`);
173
+ const last = events[events.length - 1];
174
+ if (last) {
175
+ output.push(`Last HMR Event: ${new Date(last.timestamp).toLocaleTimeString()} [${last.type}] ${last.message}`);
176
+ }
177
+ return output.join("\n");
178
+ }
179
+ export function formatHmrTrace(mode, events, limit) {
180
+ if (events.length === 0)
181
+ return "No HMR updates";
182
+ const safeLimit = normalizeLimit(limit, 20, 200);
183
+ const recent = events.slice(-safeLimit);
184
+ if (mode === "summary") {
185
+ const counts = recent.reduce((acc, event) => {
186
+ acc[event.type] = (acc[event.type] ?? 0) + 1;
187
+ return acc;
188
+ }, {});
189
+ const lines = ["# HMR Summary"];
190
+ lines.push(`Events considered: ${recent.length}`);
191
+ lines.push(`Counts: ${Object.entries(counts)
192
+ .map(([k, v]) => `${k}=${v}`)
193
+ .join(", ")}`);
194
+ const last = recent[recent.length - 1];
195
+ lines.push(`Last: ${new Date(last.timestamp).toLocaleTimeString()} [${last.type}] ${last.path ?? last.message}`);
196
+ lines.push("\nUse `vite-browser vite hmr trace --limit <n>` for timeline details.");
197
+ return lines.join("\n");
198
+ }
199
+ return [
200
+ "# HMR Trace",
201
+ ...recent.map((event) => {
202
+ const detail = event.path ? `${event.path}` : event.message;
203
+ return `[${new Date(event.timestamp).toLocaleTimeString()}] ${event.type} ${detail}`;
204
+ }),
205
+ ].join("\n");
206
+ }
207
+ export function formatModuleGraphSnapshot(rows, filter, limit = 200) {
208
+ const normalizedFilter = filter?.trim().toLowerCase();
209
+ const safeLimit = normalizeLimit(limit, 200, 500);
210
+ const filtered = rows.filter((row) => normalizedFilter ? row.url.toLowerCase().includes(normalizedFilter) : true);
211
+ const limited = filtered.slice(0, safeLimit);
212
+ if (limited.length === 0)
213
+ return "No module resources found";
214
+ const lines = [];
215
+ lines.push("# Vite Module Graph (loaded resources)");
216
+ lines.push(`Total: ${filtered.length}${filtered.length > limited.length ? ` (showing ${limited.length})` : ""}`);
217
+ lines.push("# idx initiator ms url");
218
+ lines.push("");
219
+ limited.forEach((row, idx) => {
220
+ lines.push(`${idx} ${row.initiator} ${row.durationMs}ms ${row.url}`);
221
+ });
222
+ return lines.join("\n");
223
+ }
224
+ export function formatModuleGraphTrace(currentUrls, previousUrls, filter, limit = 200) {
225
+ if (!previousUrls) {
226
+ return "No module-graph baseline. Captured current snapshot; run `vite module-graph trace` again.";
227
+ }
228
+ const currentSet = new Set(currentUrls);
229
+ const added = currentUrls.filter((url) => !previousUrls.has(url));
230
+ const removed = [...previousUrls].filter((url) => !currentSet.has(url));
231
+ const normalizedFilter = filter?.trim().toLowerCase();
232
+ const safeLimit = normalizeLimit(limit, 200, 500);
233
+ const addedFiltered = normalizedFilter
234
+ ? added.filter((url) => url.toLowerCase().includes(normalizedFilter))
235
+ : added;
236
+ const removedFiltered = normalizedFilter
237
+ ? removed.filter((url) => url.toLowerCase().includes(normalizedFilter))
238
+ : removed;
239
+ const lines = [];
240
+ lines.push("# Vite Module Graph Trace");
241
+ lines.push(`Added: ${addedFiltered.length}, Removed: ${removedFiltered.length}`);
242
+ lines.push("");
243
+ lines.push("## Added");
244
+ if (addedFiltered.length === 0)
245
+ lines.push("(none)");
246
+ else
247
+ addedFiltered.slice(0, safeLimit).forEach((url) => lines.push(`+ ${url}`));
248
+ lines.push("");
249
+ lines.push("## Removed");
250
+ if (removedFiltered.length === 0)
251
+ lines.push("(none)");
252
+ else
253
+ removedFiltered.slice(0, safeLimit).forEach((url) => lines.push(`- ${url}`));
254
+ return lines.join("\n");
255
+ }
157
256
  export async function goto(url) {
158
257
  const currentPage = await ensurePage();
159
258
  await currentPage.goto(url, { waitUntil: "domcontentloaded" });
@@ -295,19 +394,7 @@ export async function viteRuntimeStatus() {
295
394
  timestamp: Date.now(),
296
395
  };
297
396
  });
298
- const output = [];
299
- output.push("# Vite Runtime");
300
- output.push(`URL: ${runtime.url}`);
301
- output.push(`Framework: ${framework}`);
302
- output.push(`Vite Client: ${runtime.hasViteClient ? "loaded" : "not detected"}`);
303
- output.push(`HMR Socket: ${runtime.wsState}`);
304
- output.push(`Error Overlay: ${runtime.hasErrorOverlay ? "present" : "none"}`);
305
- output.push(`Tracked HMR Events: ${hmrEvents.length}`);
306
- const last = hmrEvents[hmrEvents.length - 1];
307
- if (last) {
308
- output.push(`Last HMR Event: ${new Date(last.timestamp).toLocaleTimeString()} [${last.type}] ${last.message}`);
309
- }
310
- return output.join("\n");
397
+ return formatRuntimeStatus(runtime, framework, hmrEvents);
311
398
  }
312
399
  export async function viteHMRTrace(mode, limit = 20) {
313
400
  if (!page)
@@ -331,30 +418,7 @@ export async function viteHMRTrace(mode, limit = 20) {
331
418
  }
332
419
  if (hmrEvents.length === 0)
333
420
  return "No HMR updates";
334
- const safeLimit = Number.isFinite(limit) && limit > 0 ? Math.min(limit, 200) : 20;
335
- const recent = hmrEvents.slice(-safeLimit);
336
- if (mode === "summary") {
337
- const counts = recent.reduce((acc, event) => {
338
- acc[event.type] = (acc[event.type] ?? 0) + 1;
339
- return acc;
340
- }, {});
341
- const lines = ["# HMR Summary"];
342
- lines.push(`Events considered: ${recent.length}`);
343
- lines.push(`Counts: ${Object.entries(counts)
344
- .map(([k, v]) => `${k}=${v}`)
345
- .join(", ")}`);
346
- const last = recent[recent.length - 1];
347
- lines.push(`Last: ${new Date(last.timestamp).toLocaleTimeString()} [${last.type}] ${last.path ?? last.message}`);
348
- lines.push("\nUse `vite-browser vite hmr trace --limit <n>` for timeline details.");
349
- return lines.join("\n");
350
- }
351
- return [
352
- "# HMR Trace",
353
- ...recent.map((event) => {
354
- const detail = event.path ? `${event.path}` : event.message;
355
- return `[${new Date(event.timestamp).toLocaleTimeString()}] ${event.type} ${detail}`;
356
- }),
357
- ].join("\n");
421
+ return formatHmrTrace(mode, hmrEvents, limit);
358
422
  }
359
423
  export async function viteModuleGraph(filter, limit = 200, mode = "snapshot") {
360
424
  if (!page)
@@ -366,52 +430,11 @@ export async function viteModuleGraph(filter, limit = 200, mode = "snapshot") {
366
430
  const moduleRows = await collectModuleRows(page);
367
431
  const currentUrls = moduleRows.map((row) => row.url);
368
432
  const previousUrls = lastModuleGraphUrls ? new Set(lastModuleGraphUrls) : null;
369
- const currentSet = new Set(currentUrls);
370
433
  lastModuleGraphUrls = [...currentUrls];
371
- const normalizedFilter = filter?.trim().toLowerCase();
372
- const safeLimit = Number.isFinite(limit) && limit > 0 ? Math.min(limit, 500) : 200;
373
434
  if (mode === "trace") {
374
- if (!previousUrls) {
375
- return "No module-graph baseline. Captured current snapshot; run `vite module-graph trace` again.";
376
- }
377
- const added = currentUrls.filter((url) => !previousUrls.has(url));
378
- const removed = [...previousUrls].filter((url) => !currentSet.has(url));
379
- const addedFiltered = normalizedFilter
380
- ? added.filter((url) => url.toLowerCase().includes(normalizedFilter))
381
- : added;
382
- const removedFiltered = normalizedFilter
383
- ? removed.filter((url) => url.toLowerCase().includes(normalizedFilter))
384
- : removed;
385
- const lines = [];
386
- lines.push("# Vite Module Graph Trace");
387
- lines.push(`Added: ${addedFiltered.length}, Removed: ${removedFiltered.length}`);
388
- lines.push("");
389
- lines.push("## Added");
390
- if (addedFiltered.length === 0)
391
- lines.push("(none)");
392
- else
393
- addedFiltered.slice(0, safeLimit).forEach((url) => lines.push(`+ ${url}`));
394
- lines.push("");
395
- lines.push("## Removed");
396
- if (removedFiltered.length === 0)
397
- lines.push("(none)");
398
- else
399
- removedFiltered.slice(0, safeLimit).forEach((url) => lines.push(`- ${url}`));
400
- return lines.join("\n");
435
+ return formatModuleGraphTrace(currentUrls, previousUrls, filter, limit);
401
436
  }
402
- const filtered = moduleRows.filter((row) => normalizedFilter ? row.url.toLowerCase().includes(normalizedFilter) : true);
403
- const limited = filtered.slice(0, safeLimit);
404
- if (limited.length === 0)
405
- return "No module resources found";
406
- const lines = [];
407
- lines.push("# Vite Module Graph (loaded resources)");
408
- lines.push(`Total: ${filtered.length}${filtered.length > limited.length ? ` (showing ${limited.length})` : ""}`);
409
- lines.push("# idx initiator ms url");
410
- lines.push("");
411
- limited.forEach((row, idx) => {
412
- lines.push(`${idx} ${row.initiator} ${row.durationMs}ms ${row.url}`);
413
- });
414
- return lines.join("\n");
437
+ return formatModuleGraphSnapshot(moduleRows, filter, limit);
415
438
  }
416
439
  async function collectModuleRows(page) {
417
440
  return page.evaluate(() => {
@@ -500,7 +523,7 @@ export async function network(idx) {
500
523
  return networkLog.format();
501
524
  return networkLog.detail(idx);
502
525
  }
503
- async function mapStackTrace(stack, origin, inlineSource = false) {
526
+ export async function mapStackTrace(stack, origin, inlineSource = false, resolver = resolveViaSourceMap) {
504
527
  const locationRegex = /(https?:\/\/[^\s)]+):(\d+):(\d+)/g;
505
528
  const matches = Array.from(stack.matchAll(locationRegex));
506
529
  if (matches.length === 0)
@@ -512,7 +535,7 @@ async function mapStackTrace(stack, origin, inlineSource = false) {
512
535
  const column = Number.parseInt(match[3], 10);
513
536
  if (!Number.isFinite(line) || !Number.isFinite(column))
514
537
  continue;
515
- const mapped = await resolveViaSourceMap(origin, fileUrl, line, column, inlineSource);
538
+ const mapped = await resolver(origin, fileUrl, line, column, inlineSource);
516
539
  if (!mapped)
517
540
  continue;
518
541
  mappedLines.push(`- ${fileUrl}:${line}:${column} -> ${mapped.file}:${mapped.line}:${mapped.column}`);
package/dist/cli.d.ts CHANGED
@@ -1,2 +1,14 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ import { send, type Response } from "./client.js";
3
+ export type CliIo = {
4
+ send: typeof send;
5
+ readFile: (path: string, encoding: BufferEncoding) => string;
6
+ stdout: (text: string) => void;
7
+ stderr: (text: string) => void;
8
+ exit: (code: number) => never;
9
+ };
10
+ export declare function normalizeUrl(value: string): string;
11
+ export declare function parseNumberFlag(args: string[], name: string, fallback: number): number;
12
+ export declare function runCli(argv: string[], io: CliIo): Promise<void>;
13
+ export declare function exit(io: Pick<CliIo, "stdout" | "stderr" | "exit">, res: Response, msg: string): never;
14
+ export declare function printUsage(): string;