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