tauri-plugin-debug-tools 0.1.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 (82) hide show
  1. package/AGENTS.md +346 -0
  2. package/LICENSE +21 -0
  3. package/README.md +303 -0
  4. package/dist-js/consoleLogger.d.ts +92 -0
  5. package/dist-js/consoleLogger.d.ts.map +1 -0
  6. package/dist-js/consoleLogger.js +317 -0
  7. package/dist-js/debugBridge.d.ts +50 -0
  8. package/dist-js/debugBridge.d.ts.map +1 -0
  9. package/dist-js/debugBridge.js +66 -0
  10. package/dist-js/index.d.ts +3 -0
  11. package/dist-js/index.d.ts.map +1 -0
  12. package/dist-js/index.js +2 -0
  13. package/dist-js/logAdapter.d.ts +36 -0
  14. package/dist-js/logAdapter.d.ts.map +1 -0
  15. package/dist-js/logAdapter.js +42 -0
  16. package/dist-js/screenshotHelper.d.ts +60 -0
  17. package/dist-js/screenshotHelper.d.ts.map +1 -0
  18. package/dist-js/screenshotHelper.js +100 -0
  19. package/examples/.vscode/extensions.json +3 -0
  20. package/examples/README.md +51 -0
  21. package/examples/bun.lock +265 -0
  22. package/examples/package.json +19 -0
  23. package/examples/src/assets/javascript.svg +1 -0
  24. package/examples/src/assets/tauri.svg +6 -0
  25. package/examples/src/index.html +56 -0
  26. package/examples/src/main.js +91 -0
  27. package/examples/src/styles.css +112 -0
  28. package/examples/src-tauri/Cargo.lock +5674 -0
  29. package/examples/src-tauri/Cargo.toml +25 -0
  30. package/examples/src-tauri/build.rs +3 -0
  31. package/examples/src-tauri/capabilities/default.json +7 -0
  32. package/examples/src-tauri/icons/128x128.png +0 -0
  33. package/examples/src-tauri/icons/128x128@2x.png +0 -0
  34. package/examples/src-tauri/icons/32x32.png +0 -0
  35. package/examples/src-tauri/icons/Square107x107Logo.png +0 -0
  36. package/examples/src-tauri/icons/Square142x142Logo.png +0 -0
  37. package/examples/src-tauri/icons/Square150x150Logo.png +0 -0
  38. package/examples/src-tauri/icons/Square284x284Logo.png +0 -0
  39. package/examples/src-tauri/icons/Square30x30Logo.png +0 -0
  40. package/examples/src-tauri/icons/Square310x310Logo.png +0 -0
  41. package/examples/src-tauri/icons/Square44x44Logo.png +0 -0
  42. package/examples/src-tauri/icons/Square71x71Logo.png +0 -0
  43. package/examples/src-tauri/icons/Square89x89Logo.png +0 -0
  44. package/examples/src-tauri/icons/StoreLogo.png +0 -0
  45. package/examples/src-tauri/icons/icon.icns +0 -0
  46. package/examples/src-tauri/icons/icon.ico +0 -0
  47. package/examples/src-tauri/icons/icon.png +0 -0
  48. package/examples/src-tauri/src/lib.rs +15 -0
  49. package/examples/src-tauri/src/main.rs +6 -0
  50. package/examples/src-tauri/tauri.conf.json +33 -0
  51. package/examples/tests/e2e.mac.test.ts +203 -0
  52. package/examples/tests/e2e.test.ts +131 -0
  53. package/examples/vitest.config.ts +10 -0
  54. package/guest-js/consoleLogger.ts +369 -0
  55. package/guest-js/debugBridge.ts +93 -0
  56. package/guest-js/index.ts +2 -0
  57. package/guest-js/logAdapter.ts +62 -0
  58. package/guest-js/screenshotHelper.ts +122 -0
  59. package/package.json +84 -0
  60. package/permissions/autogenerated/commands/append_debug_logs.toml +13 -0
  61. package/permissions/autogenerated/commands/capture_webview_state.toml +13 -0
  62. package/permissions/autogenerated/commands/get_console_logs.toml +13 -0
  63. package/permissions/autogenerated/commands/reset_debug_logs.toml +13 -0
  64. package/permissions/autogenerated/commands/send_debug_command.toml +13 -0
  65. package/permissions/autogenerated/commands/write_debug_snapshot.toml +13 -0
  66. package/permissions/autogenerated/reference.md +201 -0
  67. package/permissions/debug-with-logging.toml +26 -0
  68. package/permissions/default.toml +26 -0
  69. package/permissions/schemas/schema.json +384 -0
  70. package/skills/debug-tauri/SKILL.md +114 -0
  71. package/skills/debug-tauri/references/IPC_COMMANDS.md +196 -0
  72. package/skills/debug-tauri/references/LOGGING.md +195 -0
  73. package/skills/debug-tauri/references/MIGRATION.md +487 -0
  74. package/skills/debug-tauri/references/REFERENCE.md +206 -0
  75. package/skills/debug-tauri/references/REPORT_TEMPLATE.md +166 -0
  76. package/skills/debug-tauri/references/SCREENSHOTS.md +193 -0
  77. package/skills/debug-tauri/references/TROUBLESHOOTING.md +144 -0
  78. package/skills/debug-tauri/scripts/analyze_logs.sh +127 -0
  79. package/skills/debug-tauri/scripts/capture.sh +89 -0
  80. package/skills/debug-tauri/scripts/validate_setup.sh +181 -0
  81. package/src/commands.rs +147 -0
  82. package/src/lib.rs +41 -0
@@ -0,0 +1,369 @@
1
+ /**
2
+ * Collect error logs without wrapping console methods.
3
+ */
4
+
5
+ import { invoke } from "@tauri-apps/api/core";
6
+
7
+ export interface ConsoleLogEntry {
8
+ timestamp: number;
9
+ level: "log" | "warn" | "error" | "info" | "debug";
10
+ message: string;
11
+ args: unknown[];
12
+ stack_trace?: string;
13
+ }
14
+
15
+ class ConsoleLogCollector {
16
+ private logs: ConsoleLogEntry[] = [];
17
+ private readonly maxLogs = 1000; // Max size for the ring buffer.
18
+ private pendingLogs: ConsoleLogEntry[] = [];
19
+ private flushTimer: number | null = null;
20
+ private readonly flushIntervalMs = 1000;
21
+ private readonly maxPendingLogs = 200;
22
+ private tauriReady = false;
23
+ private logsReset = false;
24
+ private readonly originalConsole: {
25
+ log: typeof console.log;
26
+ warn: typeof console.warn;
27
+ error: typeof console.error;
28
+ info: typeof console.info;
29
+ debug: typeof console.debug;
30
+ };
31
+
32
+ constructor() {
33
+ // Preserve original console methods.
34
+ this.originalConsole = {
35
+ log: console.log.bind(console),
36
+ warn: console.warn.bind(console),
37
+ error: console.error.bind(console),
38
+ info: console.info.bind(console),
39
+ debug: console.debug.bind(console),
40
+ };
41
+
42
+ this.setupTauriReadyListener();
43
+ this.setupErrorHandlers();
44
+ if (this.isDev()) {
45
+ console.info("[debug] console logger initialized");
46
+ }
47
+ }
48
+
49
+ private isDev(): boolean {
50
+ return (
51
+ (import.meta as ImportMeta & { env?: { DEV?: boolean } }).env?.DEV ===
52
+ true
53
+ );
54
+ }
55
+
56
+ private setupErrorHandlers(): void {
57
+ if (typeof window === "undefined") return;
58
+
59
+ window.addEventListener("error", (event) => {
60
+ const error = event.error as Error | undefined;
61
+ const message = event.message || error?.message || "Unhandled error";
62
+ const stack = this.normalizeStack(error?.stack);
63
+ this.addLog("error", [message], stack);
64
+ });
65
+
66
+ window.addEventListener("unhandledrejection", (event) => {
67
+ const reason = event.reason;
68
+ let message = "Unhandled promise rejection";
69
+ let stack: string | undefined;
70
+ if (reason instanceof Error) {
71
+ message = reason.message;
72
+ stack = reason.stack;
73
+ } else if (typeof reason === "string") {
74
+ message = reason;
75
+ } else if (reason !== undefined) {
76
+ try {
77
+ message = JSON.stringify(reason);
78
+ } catch {
79
+ message = String(reason);
80
+ }
81
+ }
82
+ this.addLog("error", [message, reason], this.normalizeStack(stack));
83
+ });
84
+ }
85
+
86
+ private addLog(
87
+ level: ConsoleLogEntry["level"],
88
+ args: unknown[],
89
+ stack_trace?: string,
90
+ ): void {
91
+ const entry: ConsoleLogEntry = {
92
+ timestamp: Date.now(),
93
+ level,
94
+ message: this.formatArgs(args),
95
+ args,
96
+ stack_trace,
97
+ };
98
+
99
+ this.logs.push(entry);
100
+ this.enqueuePending(entry);
101
+
102
+ // Ring buffer: drop the oldest entries when over the limit.
103
+ if (this.logs.length > this.maxLogs) {
104
+ this.logs.shift();
105
+ }
106
+ }
107
+
108
+ private enqueuePending(entry: ConsoleLogEntry): void {
109
+ this.pendingLogs.push(entry);
110
+ if (this.pendingLogs.length > this.maxPendingLogs) {
111
+ this.pendingLogs.shift();
112
+ }
113
+ this.scheduleFlush();
114
+ }
115
+
116
+ private scheduleFlush(): void {
117
+ if (typeof window === "undefined") return;
118
+ if (this.flushTimer !== null) return;
119
+ this.flushTimer = window.setTimeout(() => {
120
+ this.flushTimer = null;
121
+ void this.flushPending();
122
+ }, this.flushIntervalMs);
123
+ }
124
+
125
+ private async flushPending(): Promise<void> {
126
+ if (!this.tauriReady) {
127
+ this.scheduleFlush();
128
+ return;
129
+ }
130
+ if (this.pendingLogs.length === 0) return;
131
+ const batch = this.pendingLogs.splice(0, this.pendingLogs.length);
132
+ try {
133
+ await invoke("plugin:debug-tools|append_debug_logs", { logs: batch });
134
+ } catch (error) {
135
+ this.originalConsole.error("[debug] append logs failed", error);
136
+ }
137
+ }
138
+
139
+ private setupTauriReadyListener(): void {
140
+ if (typeof window === "undefined") return;
141
+ const tauriCore = (window as Window & { __TAURI__?: { core?: unknown } })
142
+ .__TAURI__?.core;
143
+ if (tauriCore) {
144
+ this.handleTauriReady();
145
+ return;
146
+ }
147
+
148
+ window.addEventListener("tauri://ready", () => {
149
+ this.handleTauriReady();
150
+ });
151
+ }
152
+
153
+ private handleTauriReady(): void {
154
+ this.tauriReady = true;
155
+ void this.resetLogsFile().finally(() => {
156
+ void this.flushPending();
157
+ });
158
+ }
159
+
160
+ private async resetLogsFile(): Promise<void> {
161
+ if (this.logsReset) return;
162
+ this.logsReset = true;
163
+ try {
164
+ await invoke("plugin:debug-tools|reset_debug_logs");
165
+ } catch (error) {
166
+ this.originalConsole.error("[debug] reset logs failed", error);
167
+ }
168
+ }
169
+
170
+ private formatArgs(args: unknown[]): string {
171
+ return args
172
+ .map((arg) => {
173
+ if (typeof arg === "string") return arg;
174
+ if (arg instanceof Error) return `${arg.name}: ${arg.message}`;
175
+ try {
176
+ return JSON.stringify(arg);
177
+ } catch {
178
+ return String(arg);
179
+ }
180
+ })
181
+ .join(" ");
182
+ }
183
+
184
+ private formatOrigin(stack?: string): string | undefined {
185
+ if (!stack) return undefined;
186
+ const lines = stack
187
+ .split("\n")
188
+ .map((line) => line.trim())
189
+ .filter(Boolean);
190
+
191
+ for (const line of lines) {
192
+ if (line.includes("debugTools")) continue;
193
+ if (line.includes("consoleLogger")) continue;
194
+ if (line.includes("ConsoleLogCollector")) continue;
195
+ if (line.includes("node_modules")) continue;
196
+ if (line.includes("react-dom_client")) continue;
197
+ if (line.includes("guest-js")) continue;
198
+ if (line.includes("dist-js")) continue;
199
+ if (line.startsWith("Error")) continue;
200
+ return line;
201
+ }
202
+ return undefined;
203
+ }
204
+
205
+ private buildOrigin(_args: unknown[]): { origin?: string; stack?: string } {
206
+ const error = new Error();
207
+ const stack = error.stack;
208
+ const origin = this.formatOrigin(stack);
209
+ return { origin, stack };
210
+ }
211
+
212
+ private withOriginArgs(args: unknown[], origin?: string): unknown[] {
213
+ return origin ? [...args, `[origin] ${origin}`] : args;
214
+ }
215
+
216
+ public record(level: ConsoleLogEntry["level"], args: unknown[]): void {
217
+ const { origin, stack } = this.buildOrigin(args);
218
+ const enrichedArgs = this.withOriginArgs(args, origin);
219
+ this.addLog(level, enrichedArgs, this.normalizeStack(stack));
220
+ }
221
+
222
+ public log(...args: unknown[]): void {
223
+ const { origin } = this.buildOrigin(args);
224
+ const enrichedArgs = this.withOriginArgs(args, origin);
225
+ this.originalConsole.log(...enrichedArgs);
226
+ this.record("log", args);
227
+ }
228
+
229
+ public info(...args: unknown[]): void {
230
+ const { origin } = this.buildOrigin(args);
231
+ const enrichedArgs = this.withOriginArgs(args, origin);
232
+ this.originalConsole.info(...enrichedArgs);
233
+ this.record("info", args);
234
+ }
235
+
236
+ public warn(...args: unknown[]): void {
237
+ const { origin } = this.buildOrigin(args);
238
+ const enrichedArgs = this.withOriginArgs(args, origin);
239
+ this.originalConsole.warn(...enrichedArgs);
240
+ this.record("warn", args);
241
+ }
242
+
243
+ public error(...args: unknown[]): void {
244
+ const { origin } = this.buildOrigin(args);
245
+ const enrichedArgs = this.withOriginArgs(args, origin);
246
+ this.originalConsole.error(...enrichedArgs);
247
+ this.record("error", args);
248
+ }
249
+
250
+ public debug(...args: unknown[]): void {
251
+ const { origin } = this.buildOrigin(args);
252
+ const enrichedArgs = this.withOriginArgs(args, origin);
253
+ this.originalConsole.debug(...enrichedArgs);
254
+ this.record("debug", args);
255
+ }
256
+
257
+ private normalizeStack(stack?: string): string | undefined {
258
+ if (!stack) return undefined;
259
+ const cleaned = this.cleanStack(stack);
260
+ return cleaned ?? stack;
261
+ }
262
+
263
+ private cleanStack(stack: string): string | null {
264
+ const lines = stack.split("\n");
265
+ if (lines.length <= 1) return null;
266
+ const header = lines[0];
267
+ const filtered = lines
268
+ .slice(1)
269
+ .filter((line) => !line.includes("consoleLogger"))
270
+ .filter((line) => !line.includes("ConsoleLogCollector"));
271
+ if (filtered.length === 0) return null;
272
+ return [header, ...filtered].join("\n");
273
+ }
274
+
275
+ /**
276
+ * Get all logs.
277
+ */
278
+ public getLogs(): ConsoleLogEntry[] {
279
+ return [...this.logs];
280
+ }
281
+
282
+ /**
283
+ * Get logs by level.
284
+ */
285
+ public getLogsByLevel(level: ConsoleLogEntry["level"]): ConsoleLogEntry[] {
286
+ return this.logs.filter((log) => log.level === level);
287
+ }
288
+
289
+ /**
290
+ * Get error logs only.
291
+ */
292
+ public getErrors(): ConsoleLogEntry[] {
293
+ return this.getLogsByLevel("error");
294
+ }
295
+
296
+ /**
297
+ * Get the latest N logs.
298
+ */
299
+ public getRecentLogs(count: number): ConsoleLogEntry[] {
300
+ return this.logs.slice(-count);
301
+ }
302
+
303
+ /**
304
+ * Clear logs.
305
+ */
306
+ public clearLogs(): void {
307
+ this.logs = [];
308
+ }
309
+
310
+ /**
311
+ * Get log statistics.
312
+ */
313
+ public getStats(): {
314
+ total: number;
315
+ byLevel: Record<ConsoleLogEntry["level"], number>;
316
+ } {
317
+ const byLevel: Record<ConsoleLogEntry["level"], number> = {
318
+ log: 0,
319
+ warn: 0,
320
+ error: 0,
321
+ info: 0,
322
+ debug: 0,
323
+ };
324
+
325
+ for (const log of this.logs) {
326
+ byLevel[log.level]++;
327
+ }
328
+
329
+ return {
330
+ total: this.logs.length,
331
+ byLevel,
332
+ };
333
+ }
334
+ }
335
+
336
+ // Singleton instance.
337
+ export const consoleLogger = new ConsoleLogCollector();
338
+
339
+ export const debugTools = {
340
+ log: (...args: unknown[]) => consoleLogger.log(...args),
341
+ info: (...args: unknown[]) => consoleLogger.info(...args),
342
+ warn: (...args: unknown[]) => consoleLogger.warn(...args),
343
+ error: (...args: unknown[]) => consoleLogger.error(...args),
344
+ debug: (...args: unknown[]) => consoleLogger.debug(...args),
345
+ record: (level: ConsoleLogEntry["level"], args: unknown[]) =>
346
+ consoleLogger.record(level, args),
347
+ };
348
+
349
+ export const log = (...args: unknown[]) => consoleLogger.log(...args);
350
+ export const info = (...args: unknown[]) => consoleLogger.info(...args);
351
+ export const warn = (...args: unknown[]) => consoleLogger.warn(...args);
352
+ export const error = (...args: unknown[]) => consoleLogger.error(...args);
353
+ export const debug = (...args: unknown[]) => consoleLogger.debug(...args);
354
+ export const record = (level: ConsoleLogEntry["level"], args: unknown[]) =>
355
+ consoleLogger.record(level, args);
356
+
357
+ // Expose globally so debugBridge can read logs.
358
+ if (typeof window !== "undefined") {
359
+ (
360
+ window as Window & { __consoleLogger?: ConsoleLogCollector }
361
+ ).__consoleLogger = consoleLogger;
362
+ }
363
+
364
+ // Global type definition.
365
+ declare global {
366
+ interface Window {
367
+ __consoleLogger?: ConsoleLogCollector;
368
+ }
369
+ }
@@ -0,0 +1,93 @@
1
+ import { invoke } from "@tauri-apps/api/core";
2
+ import type { ConsoleLogEntry } from "./consoleLogger";
3
+
4
+ export interface WebViewState {
5
+ url: string;
6
+ title: string;
7
+ user_agent: string;
8
+ viewport: {
9
+ width: number;
10
+ height: number;
11
+ };
12
+ }
13
+
14
+ export interface ConsoleMessage {
15
+ level: string;
16
+ message: string;
17
+ timestamp: number;
18
+ }
19
+
20
+ /**
21
+ * Get WebView state.
22
+ */
23
+ export async function captureWebViewState(): Promise<WebViewState> {
24
+ return await invoke<WebViewState>("plugin:debug-tools|capture_webview_state");
25
+ }
26
+
27
+ /**
28
+ * Get console logs (from the frontend logger).
29
+ * This works without opening Safari DevTools.
30
+ */
31
+ export function getConsoleLogs(): ConsoleLogEntry[] {
32
+ if (typeof window !== "undefined" && window.__consoleLogger) {
33
+ return window.__consoleLogger.getLogs();
34
+ }
35
+ return [];
36
+ }
37
+
38
+ /**
39
+ * Get error logs only.
40
+ */
41
+ export function getConsoleErrors(): ConsoleLogEntry[] {
42
+ if (typeof window !== "undefined" && window.__consoleLogger) {
43
+ return window.__consoleLogger.getErrors();
44
+ }
45
+ return [];
46
+ }
47
+
48
+ /**
49
+ * Get the latest N logs.
50
+ */
51
+ export function getRecentConsoleLogs(count = 50): ConsoleLogEntry[] {
52
+ if (typeof window !== "undefined" && window.__consoleLogger) {
53
+ return window.__consoleLogger.getRecentLogs(count);
54
+ }
55
+ return [];
56
+ }
57
+
58
+ /**
59
+ * Get log statistics.
60
+ */
61
+ export function getConsoleLogStats() {
62
+ if (typeof window !== "undefined" && window.__consoleLogger) {
63
+ return window.__consoleLogger.getStats();
64
+ }
65
+ return {
66
+ total: 0,
67
+ byLevel: { log: 0, warn: 0, error: 0, info: 0, debug: 0 },
68
+ };
69
+ }
70
+
71
+ /**
72
+ * Clear logs.
73
+ */
74
+ export function clearConsoleLogs(): void {
75
+ if (typeof window !== "undefined" && window.__consoleLogger) {
76
+ window.__consoleLogger.clearLogs();
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Send a debug command (event-based).
82
+ * @param command Command name
83
+ * @param payload Payload data
84
+ */
85
+ export async function sendDebugCommand(
86
+ command: string,
87
+ payload: Record<string, unknown>,
88
+ ): Promise<string> {
89
+ return await invoke<string>("plugin:debug-tools|send_debug_command", {
90
+ command,
91
+ payload,
92
+ });
93
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./consoleLogger";
2
+ export * from "./debugBridge";
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Log Adapter for tauri-plugin-log
3
+ *
4
+ * Provides a unified interface to the official Tauri logging plugin.
5
+ * Automatically handles console attachment and structured logging.
6
+ */
7
+
8
+ import {
9
+ attachConsole,
10
+ debug,
11
+ error,
12
+ info,
13
+ trace,
14
+ warn,
15
+ } from "@tauri-apps/plugin-log";
16
+
17
+ export interface Logger {
18
+ trace: typeof trace;
19
+ debug: typeof debug;
20
+ info: typeof info;
21
+ warn: typeof warn;
22
+ error: typeof error;
23
+ initialize: () => Promise<() => void>;
24
+ }
25
+
26
+ /**
27
+ * Official plugin-based logger
28
+ *
29
+ * Usage:
30
+ * ```typescript
31
+ * import { logger } from 'tauri-plugin-debug-tools/logAdapter';
32
+ *
33
+ * // Initialize (call once at app startup)
34
+ * const detach = await logger.initialize();
35
+ *
36
+ * // Use structured logging
37
+ * logger.info('App started');
38
+ * logger.error('Something went wrong');
39
+ *
40
+ * // Cleanup (optional, on app shutdown)
41
+ * detach();
42
+ * ```
43
+ */
44
+ export const logger: Logger = {
45
+ trace,
46
+ debug,
47
+ info,
48
+ warn,
49
+ error,
50
+
51
+ /**
52
+ * Initialize logging by attaching console.
53
+ *
54
+ * This automatically forwards all console.* calls to the plugin.
55
+ * Returns a detach function to stop console forwarding.
56
+ */
57
+ async initialize() {
58
+ return await attachConsole();
59
+ },
60
+ };
61
+
62
+ export default logger;
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Screenshot Helper for tauri-plugin-screenshots
3
+ *
4
+ * Provides simplified screenshot capture utilities.
5
+ */
6
+
7
+ import {
8
+ getMonitorScreenshot,
9
+ getScreenshotableMonitors,
10
+ getScreenshotableWindows,
11
+ getWindowScreenshot,
12
+ } from "tauri-plugin-screenshots-api";
13
+
14
+ /**
15
+ * Capture screenshot of the main (first) window
16
+ *
17
+ * @returns Path to saved screenshot, or null if no windows available
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const path = await captureMainWindow();
22
+ * if (path) {
23
+ * console.log(`Screenshot saved: ${path}`);
24
+ * }
25
+ * ```
26
+ */
27
+ export async function captureMainWindow(): Promise<string | null> {
28
+ try {
29
+ const windows = await getScreenshotableWindows();
30
+
31
+ if (windows.length === 0) {
32
+ console.warn("No windows available for screenshot");
33
+ return null;
34
+ }
35
+
36
+ return await getWindowScreenshot(windows[0].id);
37
+ } catch (error) {
38
+ console.error("Failed to capture main window:", error);
39
+ return null;
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Capture screenshots of all available windows
45
+ *
46
+ * @returns Array of screenshot paths
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const paths = await captureAllWindows();
51
+ * console.log(`Captured ${paths.length} screenshots`);
52
+ * ```
53
+ */
54
+ export async function captureAllWindows(): Promise<string[]> {
55
+ try {
56
+ const windows = await getScreenshotableWindows();
57
+
58
+ const screenshots = await Promise.all(
59
+ windows.map((window: { id: number }) => getWindowScreenshot(window.id)),
60
+ );
61
+
62
+ return screenshots;
63
+ } catch (error) {
64
+ console.error("Failed to capture all windows:", error);
65
+ return [];
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Capture screenshot of the primary monitor
71
+ *
72
+ * @returns Path to saved screenshot, or null if no monitors available
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const path = await capturePrimaryMonitor();
77
+ * if (path) {
78
+ * console.log(`Monitor screenshot saved: ${path}`);
79
+ * }
80
+ * ```
81
+ */
82
+ export async function capturePrimaryMonitor(): Promise<string | null> {
83
+ try {
84
+ const monitors = await getScreenshotableMonitors();
85
+
86
+ if (monitors.length === 0) {
87
+ console.warn("No monitors available for screenshot");
88
+ return null;
89
+ }
90
+
91
+ return await getMonitorScreenshot(monitors[0].id);
92
+ } catch (error) {
93
+ console.error("Failed to capture primary monitor:", error);
94
+ return null;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Get list of all screenshotable windows
100
+ *
101
+ * @returns Array of window information
102
+ */
103
+ export async function listWindows() {
104
+ return await getScreenshotableWindows();
105
+ }
106
+
107
+ /**
108
+ * Get list of all screenshotable monitors
109
+ *
110
+ * @returns Array of monitor information
111
+ */
112
+ export async function listMonitors() {
113
+ return await getScreenshotableMonitors();
114
+ }
115
+
116
+ // Re-export core functions for advanced usage
117
+ export {
118
+ getScreenshotableWindows,
119
+ getWindowScreenshot,
120
+ getScreenshotableMonitors,
121
+ getMonitorScreenshot,
122
+ };