tauri-agent-tools 0.5.1 → 0.7.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 (128) hide show
  1. package/.agents/skills/tauri-agent-tools/SKILL.md +195 -13
  2. package/.agents/skills/tauri-bridge-setup/SKILL.md +82 -14
  3. package/.agents/skills/tauri-debug-quickstart/SKILL.md +80 -0
  4. package/AGENTS.md +9 -7
  5. package/README.md +119 -11
  6. package/dist/bridge/client.d.ts +21 -2
  7. package/dist/bridge/client.js +119 -3
  8. package/dist/bridge/client.js.map +1 -1
  9. package/dist/cli.js +47 -0
  10. package/dist/cli.js.map +1 -1
  11. package/dist/commands/appPaths.d.ts +2 -0
  12. package/dist/commands/appPaths.js +97 -0
  13. package/dist/commands/appPaths.js.map +1 -0
  14. package/dist/commands/capabilitiesAudit.d.ts +2 -0
  15. package/dist/commands/capabilitiesAudit.js +105 -0
  16. package/dist/commands/capabilitiesAudit.js.map +1 -0
  17. package/dist/commands/capture.d.ts +3 -0
  18. package/dist/commands/capture.js +218 -0
  19. package/dist/commands/capture.js.map +1 -0
  20. package/dist/commands/check.d.ts +5 -0
  21. package/dist/commands/check.js +174 -0
  22. package/dist/commands/check.js.map +1 -0
  23. package/dist/commands/configInspect.d.ts +2 -0
  24. package/dist/commands/configInspect.js +223 -0
  25. package/dist/commands/configInspect.js.map +1 -0
  26. package/dist/commands/diagnose.d.ts +2 -0
  27. package/dist/commands/diagnose.js +311 -0
  28. package/dist/commands/diagnose.js.map +1 -0
  29. package/dist/commands/eval.js +16 -3
  30. package/dist/commands/eval.js.map +1 -1
  31. package/dist/commands/forensics.d.ts +2 -0
  32. package/dist/commands/forensics.js +331 -0
  33. package/dist/commands/forensics.js.map +1 -0
  34. package/dist/commands/health.d.ts +2 -0
  35. package/dist/commands/health.js +39 -0
  36. package/dist/commands/health.js.map +1 -0
  37. package/dist/commands/interact/click.d.ts +6 -0
  38. package/dist/commands/interact/click.js +102 -0
  39. package/dist/commands/interact/click.js.map +1 -0
  40. package/dist/commands/interact/focus.d.ts +3 -0
  41. package/dist/commands/interact/focus.js +40 -0
  42. package/dist/commands/interact/focus.js.map +1 -0
  43. package/dist/commands/interact/navigate.d.ts +3 -0
  44. package/dist/commands/interact/navigate.js +49 -0
  45. package/dist/commands/interact/navigate.js.map +1 -0
  46. package/dist/commands/interact/scroll.d.ts +11 -0
  47. package/dist/commands/interact/scroll.js +110 -0
  48. package/dist/commands/interact/scroll.js.map +1 -0
  49. package/dist/commands/interact/select.d.ts +3 -0
  50. package/dist/commands/interact/select.js +59 -0
  51. package/dist/commands/interact/select.js.map +1 -0
  52. package/dist/commands/interact/shared.d.ts +23 -0
  53. package/dist/commands/interact/shared.js +62 -0
  54. package/dist/commands/interact/shared.js.map +1 -0
  55. package/dist/commands/interact/type.d.ts +6 -0
  56. package/dist/commands/interact/type.js +59 -0
  57. package/dist/commands/interact/type.js.map +1 -0
  58. package/dist/commands/invoke.d.ts +3 -0
  59. package/dist/commands/invoke.js +53 -0
  60. package/dist/commands/invoke.js.map +1 -0
  61. package/dist/commands/osLogs.d.ts +2 -0
  62. package/dist/commands/osLogs.js +130 -0
  63. package/dist/commands/osLogs.js.map +1 -0
  64. package/dist/commands/probe.d.ts +2 -0
  65. package/dist/commands/probe.js +117 -0
  66. package/dist/commands/probe.js.map +1 -0
  67. package/dist/commands/processTree.d.ts +2 -0
  68. package/dist/commands/processTree.js +45 -0
  69. package/dist/commands/processTree.js.map +1 -0
  70. package/dist/commands/shared.d.ts +10 -4
  71. package/dist/commands/shared.js +23 -3
  72. package/dist/commands/shared.js.map +1 -1
  73. package/dist/commands/sidecarReplay.d.ts +7 -0
  74. package/dist/commands/sidecarReplay.js +93 -0
  75. package/dist/commands/sidecarReplay.js.map +1 -0
  76. package/dist/commands/sidecarTap.d.ts +2 -0
  77. package/dist/commands/sidecarTap.js +118 -0
  78. package/dist/commands/sidecarTap.js.map +1 -0
  79. package/dist/commands/storeInspect.d.ts +13 -0
  80. package/dist/commands/storeInspect.js +156 -0
  81. package/dist/commands/storeInspect.js.map +1 -0
  82. package/dist/commands/webviewAttach.d.ts +2 -0
  83. package/dist/commands/webviewAttach.js +64 -0
  84. package/dist/commands/webviewAttach.js.map +1 -0
  85. package/dist/platform/oslog/darwin.d.ts +21 -0
  86. package/dist/platform/oslog/darwin.js +72 -0
  87. package/dist/platform/oslog/darwin.js.map +1 -0
  88. package/dist/platform/oslog/linux.d.ts +16 -0
  89. package/dist/platform/oslog/linux.js +47 -0
  90. package/dist/platform/oslog/linux.js.map +1 -0
  91. package/dist/platform/oslog/windows.d.ts +15 -0
  92. package/dist/platform/oslog/windows.js +16 -0
  93. package/dist/platform/oslog/windows.js.map +1 -0
  94. package/dist/schemas/bridge.d.ts +256 -0
  95. package/dist/schemas/bridge.js +57 -0
  96. package/dist/schemas/bridge.js.map +1 -1
  97. package/dist/schemas/commands.d.ts +126 -0
  98. package/dist/schemas/commands.js +28 -0
  99. package/dist/schemas/commands.js.map +1 -1
  100. package/dist/schemas/index.d.ts +3 -2
  101. package/dist/schemas/index.js +3 -2
  102. package/dist/schemas/index.js.map +1 -1
  103. package/dist/schemas/interact.d.ts +118 -0
  104. package/dist/schemas/interact.js +31 -0
  105. package/dist/schemas/interact.js.map +1 -0
  106. package/dist/schemas/osLog.d.ts +34 -0
  107. package/dist/schemas/osLog.js +18 -0
  108. package/dist/schemas/osLog.js.map +1 -0
  109. package/dist/schemas/sidecar.d.ts +33 -0
  110. package/dist/schemas/sidecar.js +17 -0
  111. package/dist/schemas/sidecar.js.map +1 -0
  112. package/dist/schemas/tauriConfig.d.ts +825 -0
  113. package/dist/schemas/tauriConfig.js +102 -0
  114. package/dist/schemas/tauriConfig.js.map +1 -0
  115. package/dist/util/ndjson.d.ts +37 -0
  116. package/dist/util/ndjson.js +82 -0
  117. package/dist/util/ndjson.js.map +1 -0
  118. package/dist/util/tauriConfig.d.ts +63 -0
  119. package/dist/util/tauriConfig.js +235 -0
  120. package/dist/util/tauriConfig.js.map +1 -0
  121. package/examples/frontend-stub/index.html +1 -0
  122. package/examples/tauri-bridge/Cargo.toml +6 -0
  123. package/examples/tauri-bridge/build.rs +3 -0
  124. package/examples/tauri-bridge/icons/icon.png +0 -0
  125. package/examples/tauri-bridge/src/dev_bridge.rs +509 -10
  126. package/examples/tauri-bridge/tauri.conf.json +25 -0
  127. package/package.json +3 -1
  128. package/rust-bridge/README.md +7 -5
@@ -0,0 +1,105 @@
1
+ import { Command } from 'commander';
2
+ import { addBridgeOptions, resolveBridge } from './shared.js';
3
+ const OVERBROAD_PERMISSIONS = new Set([
4
+ 'fs:allow-all',
5
+ 'fs:default',
6
+ 'shell:allow-execute',
7
+ 'shell:allow-spawn',
8
+ 'http:allow-all',
9
+ ]);
10
+ export function registerCapabilitiesAudit(program) {
11
+ const cmd = new Command('capabilities')
12
+ .description('Audit Tauri capabilities live from a running app (requires bridge v0.7.0+)');
13
+ const sub = cmd
14
+ .command('audit')
15
+ .description('Fetch the live capability set from the bridge and flag risky permissions')
16
+ .option('--json', 'Output as JSON');
17
+ addBridgeOptions(sub);
18
+ sub.action(async (opts) => {
19
+ const bridge = await resolveBridge(opts);
20
+ const caps = await bridge.capabilities();
21
+ const findings = audit(caps);
22
+ const out = {
23
+ windows: caps.windows,
24
+ capabilities: caps.declared,
25
+ findings,
26
+ };
27
+ if (opts.json) {
28
+ console.log(JSON.stringify(out, null, 2));
29
+ return;
30
+ }
31
+ renderHuman(out);
32
+ });
33
+ program.addCommand(cmd);
34
+ }
35
+ function audit(caps) {
36
+ const findings = [];
37
+ for (const cap of caps.declared) {
38
+ if (cap.permissions.length === 0) {
39
+ // Capability declared by JSON-file reference is reported as a bare
40
+ // identifier with no permissions array — the bridge can't read the file.
41
+ // Surface it as info so the user knows we don't have details.
42
+ findings.push({
43
+ level: 'info',
44
+ capability: cap.identifier,
45
+ message: 'Permissions list is empty (capability may be declared by file reference; use `config inspect` for static analysis)',
46
+ });
47
+ continue;
48
+ }
49
+ for (const perm of cap.permissions) {
50
+ if (perm === '*') {
51
+ findings.push({
52
+ level: 'error',
53
+ capability: cap.identifier,
54
+ message: 'Grants wildcard permission "*"',
55
+ });
56
+ continue;
57
+ }
58
+ if (OVERBROAD_PERMISSIONS.has(perm)) {
59
+ findings.push({
60
+ level: 'warn',
61
+ capability: cap.identifier,
62
+ message: `Uses over-broad permission "${perm}"`,
63
+ });
64
+ }
65
+ }
66
+ if (cap.windows.length === 0) {
67
+ findings.push({
68
+ level: 'info',
69
+ capability: cap.identifier,
70
+ message: 'No window scope declared — capability applies to all windows',
71
+ });
72
+ }
73
+ else {
74
+ const unknown = cap.windows.filter((w) => !caps.windows.includes(w) && !w.includes('*') && !w.includes('?'));
75
+ if (unknown.length > 0) {
76
+ findings.push({
77
+ level: 'warn',
78
+ capability: cap.identifier,
79
+ message: `References window label(s) not registered with this app: ${unknown.join(', ')}`,
80
+ });
81
+ }
82
+ }
83
+ }
84
+ return findings;
85
+ }
86
+ function renderHuman(out) {
87
+ console.log(`Live windows (${out.windows.length}): ${out.windows.join(', ') || '(none)'}`);
88
+ console.log(`Capabilities (${out.capabilities.length}):`);
89
+ for (const cap of out.capabilities) {
90
+ const winScope = cap.windows.length === 0 ? 'all windows' : cap.windows.join(', ');
91
+ console.log(` [${cap.identifier}] ${cap.permissions.length} permission(s), scope: ${winScope}`);
92
+ if (cap.description)
93
+ console.log(` ${cap.description}`);
94
+ }
95
+ if (out.findings.length === 0) {
96
+ console.log('\nNo findings.');
97
+ return;
98
+ }
99
+ console.log(`\nFindings (${out.findings.length}):`);
100
+ for (const f of out.findings) {
101
+ const tag = f.level.toUpperCase().padEnd(5);
102
+ console.log(` ${tag} [${f.capability}] ${f.message}`);
103
+ }
104
+ }
105
+ //# sourceMappingURL=capabilitiesAudit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilitiesAudit.js","sourceRoot":"","sources":["../../src/commands/capabilitiesAudit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ import type { PlatformAdapter } from '../types.js';
3
+ export declare function registerCapture(program: Command, getAdapter: () => PlatformAdapter | Promise<PlatformAdapter>): void;
@@ -0,0 +1,218 @@
1
+ import { writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { Command } from 'commander';
4
+ import { addBridgeOptions, resolveBridge } from './shared.js';
5
+ import { buildSerializerScript } from './dom.js';
6
+ import { computeCropRect, cropImage } from '../util/image.js';
7
+ import { DomNodeSchema } from '../schemas/dom.js';
8
+ import { PageStateSchema, SnapshotStorageResultSchema } from '../schemas/commands.js';
9
+ const PAGE_STATE_SCRIPT = `(() => {
10
+ return JSON.stringify({
11
+ url: window.location.href,
12
+ title: document.title,
13
+ viewport: { width: window.innerWidth, height: window.innerHeight },
14
+ scroll: { x: Math.round(window.scrollX), y: Math.round(window.scrollY) },
15
+ document: { width: document.documentElement.scrollWidth, height: document.documentElement.scrollHeight },
16
+ hasTauri: !!(window.__TAURI__)
17
+ });
18
+ })()`;
19
+ const STORAGE_SCRIPT = `(() => {
20
+ var local = Object.keys(localStorage).map(function(k) { return { key: k, value: localStorage.getItem(k) }; });
21
+ var session = Object.keys(sessionStorage).map(function(k) { return { key: k, value: sessionStorage.getItem(k) }; });
22
+ return JSON.stringify({ localStorage: local, sessionStorage: session });
23
+ })()`;
24
+ const INJECT_CONSOLE_ERROR_SCRIPT = `(() => {
25
+ if (!window.__captureErrors) {
26
+ window.__captureErrors = [];
27
+ const orig = console.error.bind(console);
28
+ console.error = function(...args) {
29
+ window.__captureErrors.push({ ts: Date.now(), msg: args.map(String).join(' ') });
30
+ orig(...args);
31
+ };
32
+ }
33
+ return 'ok';
34
+ })()`;
35
+ const DRAIN_CONSOLE_ERRORS_SCRIPT = `(() => {
36
+ var errs = window.__captureErrors || [];
37
+ window.__captureErrors = [];
38
+ return JSON.stringify(errs);
39
+ })()`;
40
+ async function resolveWindowId(adapter, bridge, title) {
41
+ if (title)
42
+ return adapter.findWindow(title);
43
+ const docTitle = await bridge.getDocumentTitle();
44
+ if (!docTitle)
45
+ throw new Error('Could not get window title. Use --title.');
46
+ return adapter.findWindow(docTitle);
47
+ }
48
+ export function registerCapture(program, getAdapter) {
49
+ const cmd = new Command('capture')
50
+ .description('Capture enhanced snapshot with manifest directory (screenshot, DOM, state, logs, errors)')
51
+ .requiredOption('-o, --output <dir>', 'Output directory path')
52
+ .option('-s, --selector <css>', 'CSS selector to screenshot (full window if omitted)')
53
+ .option('-t, --title <regex>', 'Window title to match (default: auto-discover)')
54
+ .option('--dom-depth <number>', 'DOM tree depth', parseInt, 3)
55
+ .option('--eval <js>', 'Additional JS to eval and save')
56
+ .option('--logs-duration <ms>', 'Duration to wait for console errors (ms)', parseInt, 3000)
57
+ .option('--json', 'Output structured manifest');
58
+ addBridgeOptions(cmd);
59
+ cmd.action(async (opts) => {
60
+ const bridge = await resolveBridge(opts);
61
+ const adapter = await getAdapter();
62
+ const outDir = opts.output;
63
+ const format = 'png';
64
+ const files = {};
65
+ // 1. Create output directory
66
+ await mkdir(outDir, { recursive: true });
67
+ // 2. Inject console error capture
68
+ try {
69
+ await bridge.eval(INJECT_CONSOLE_ERROR_SCRIPT);
70
+ }
71
+ catch {
72
+ // Non-fatal — continue without error capture
73
+ }
74
+ // 3. Get page state — save to page-state.json
75
+ let capturedUrl;
76
+ let capturedTitle;
77
+ let capturedViewport;
78
+ try {
79
+ const raw = await bridge.eval(PAGE_STATE_SCRIPT);
80
+ const parsed = PageStateSchema.parse(JSON.parse(String(raw)));
81
+ capturedUrl = parsed.url;
82
+ capturedTitle = parsed.title;
83
+ capturedViewport = parsed.viewport;
84
+ const path = join(outDir, 'page-state.json');
85
+ await writeFile(path, JSON.stringify(parsed, null, 2));
86
+ files['page-state.json'] = path;
87
+ }
88
+ catch (err) {
89
+ files['page-state.json'] = `error: ${err instanceof Error ? err.message : String(err)}`;
90
+ }
91
+ // 4. Screenshot — save to screenshot.png
92
+ try {
93
+ const windowId = await resolveWindowId(adapter, bridge, opts.title);
94
+ let buffer;
95
+ if (opts.selector) {
96
+ const elementRect = await bridge.getElementRect(opts.selector);
97
+ if (!elementRect)
98
+ throw new Error(`Element not found: ${opts.selector}`);
99
+ const viewport = await bridge.getViewportSize();
100
+ const windowGeom = await adapter.getWindowGeometry(windowId);
101
+ buffer = await adapter.captureWindow(windowId, format);
102
+ const cropRect = computeCropRect(elementRect, viewport, {
103
+ width: windowGeom.width,
104
+ height: windowGeom.height,
105
+ });
106
+ buffer = await cropImage(buffer, cropRect, format);
107
+ }
108
+ else {
109
+ buffer = await adapter.captureWindow(windowId, format);
110
+ }
111
+ const path = join(outDir, 'screenshot.png');
112
+ await writeFile(path, buffer);
113
+ files['screenshot.png'] = path;
114
+ }
115
+ catch (err) {
116
+ files['screenshot.png'] = `error: ${err instanceof Error ? err.message : String(err)}`;
117
+ }
118
+ // 5. DOM tree — save to dom.json
119
+ try {
120
+ const raw = await bridge.eval(buildSerializerScript('body', opts.domDepth, false));
121
+ const parsed = DomNodeSchema.parse(JSON.parse(String(raw)));
122
+ const path = join(outDir, 'dom.json');
123
+ await writeFile(path, JSON.stringify(parsed, null, 2));
124
+ files['dom.json'] = path;
125
+ }
126
+ catch (err) {
127
+ files['dom.json'] = `error: ${err instanceof Error ? err.message : String(err)}`;
128
+ }
129
+ // 6. Storage — save to storage.json
130
+ try {
131
+ const raw = await bridge.eval(STORAGE_SCRIPT);
132
+ const parsed = SnapshotStorageResultSchema.parse(JSON.parse(String(raw)));
133
+ const path = join(outDir, 'storage.json');
134
+ await writeFile(path, JSON.stringify(parsed, null, 2));
135
+ files['storage.json'] = path;
136
+ }
137
+ catch (err) {
138
+ files['storage.json'] = `error: ${err instanceof Error ? err.message : String(err)}`;
139
+ }
140
+ // 7. Wait for logs-duration, drain console errors — save to console-errors.json
141
+ try {
142
+ await new Promise((resolve) => setTimeout(resolve, opts.logsDuration));
143
+ const raw = await bridge.eval(DRAIN_CONSOLE_ERRORS_SCRIPT);
144
+ const errors = JSON.parse(String(raw));
145
+ const path = join(outDir, 'console-errors.json');
146
+ await writeFile(path, JSON.stringify(errors, null, 2));
147
+ files['console-errors.json'] = path;
148
+ }
149
+ catch (err) {
150
+ files['console-errors.json'] = `error: ${err instanceof Error ? err.message : String(err)}`;
151
+ }
152
+ // 8. Fetch rust logs — save to rust-logs.json
153
+ try {
154
+ const logs = await bridge.fetchLogs();
155
+ const path = join(outDir, 'rust-logs.json');
156
+ await writeFile(path, JSON.stringify(logs, null, 2));
157
+ files['rust-logs.json'] = path;
158
+ }
159
+ catch (err) {
160
+ files['rust-logs.json'] = `error: ${err instanceof Error ? err.message : String(err)}`;
161
+ }
162
+ // 9. Optional custom eval — save to eval.json
163
+ if (opts.eval) {
164
+ try {
165
+ const raw = await bridge.eval(opts.eval);
166
+ const parsed = typeof raw === 'string'
167
+ ? (() => { try {
168
+ return JSON.parse(raw);
169
+ }
170
+ catch {
171
+ return raw;
172
+ } })()
173
+ : raw;
174
+ const path = join(outDir, 'eval.json');
175
+ await writeFile(path, JSON.stringify(parsed, null, 2));
176
+ files['eval.json'] = path;
177
+ }
178
+ catch (err) {
179
+ files['eval.json'] = `error: ${err instanceof Error ? err.message : String(err)}`;
180
+ }
181
+ }
182
+ // 10. Write manifest.json
183
+ const errorCount = Object.values(files).filter(v => v.startsWith('error: ')).length;
184
+ const manifest = {
185
+ timestamp: new Date().toISOString(),
186
+ url: capturedUrl,
187
+ title: capturedTitle,
188
+ viewport: capturedViewport,
189
+ errorCount,
190
+ files,
191
+ };
192
+ const manifestPath = join(outDir, 'manifest.json');
193
+ await writeFile(manifestPath, JSON.stringify(manifest, null, 2));
194
+ // 11. Output
195
+ if (opts.json) {
196
+ console.log(JSON.stringify(manifest, null, 2));
197
+ }
198
+ else {
199
+ console.log(`Capture: ${outDir}`);
200
+ console.log(`Time: ${manifest.timestamp}`);
201
+ if (capturedUrl)
202
+ console.log(`URL: ${capturedUrl}`);
203
+ if (capturedTitle)
204
+ console.log(`Title: ${capturedTitle}`);
205
+ console.log('');
206
+ for (const [key, value] of Object.entries(files)) {
207
+ const isError = value.startsWith('error: ');
208
+ const status = isError ? 'FAIL' : ' OK';
209
+ console.log(`[${status}] ${key}: ${value}`);
210
+ }
211
+ if (errorCount > 0) {
212
+ console.log(`\n${errorCount} artifact(s) failed.`);
213
+ }
214
+ }
215
+ });
216
+ program.addCommand(cmd);
217
+ }
218
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/commands/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Command } from 'commander';
2
+ export declare function buildSelectorCheck(selector: string): string;
3
+ export declare function buildEvalCheck(expression: string): string;
4
+ export declare function buildTextCheck(pattern: string): string;
5
+ export declare function registerCheck(program: Command): void;
@@ -0,0 +1,174 @@
1
+ import { Command } from 'commander';
2
+ import { addBridgeOptions, resolveBridge } from './shared.js';
3
+ const ERROR_PATCH_SCRIPT = `(() => {
4
+ if (window.__tauriDevToolsErrorPatched) return 'already_patched';
5
+ window.__tauriDevToolsOriginalConsoleError = console.error;
6
+ window.__tauriDevToolsErrorBuffer = [];
7
+ console.error = function() {
8
+ var args = Array.prototype.slice.call(arguments);
9
+ var message = args.map(function(a) {
10
+ return typeof a === 'object' ? JSON.stringify(a) : String(a);
11
+ }).join(' ');
12
+ window.__tauriDevToolsErrorBuffer.push(message);
13
+ window.__tauriDevToolsOriginalConsoleError.apply(console, arguments);
14
+ };
15
+ window.__tauriDevToolsErrorPatched = true;
16
+ return 'patched';
17
+ })()`;
18
+ const ERROR_DRAIN_SCRIPT = `(() => {
19
+ var buf = window.__tauriDevToolsErrorBuffer || [];
20
+ window.__tauriDevToolsErrorBuffer = [];
21
+ return JSON.stringify(buf);
22
+ })()`;
23
+ const ERROR_CLEANUP_SCRIPT = `(() => {
24
+ if (window.__tauriDevToolsOriginalConsoleError) {
25
+ console.error = window.__tauriDevToolsOriginalConsoleError;
26
+ delete window.__tauriDevToolsOriginalConsoleError;
27
+ delete window.__tauriDevToolsErrorBuffer;
28
+ delete window.__tauriDevToolsErrorPatched;
29
+ }
30
+ return 'cleaned';
31
+ })()`;
32
+ export function buildSelectorCheck(selector) {
33
+ const escaped = selector.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
34
+ return `!!document.querySelector('${escaped}')`;
35
+ }
36
+ export function buildEvalCheck(expression) {
37
+ return `!!(${expression})`;
38
+ }
39
+ export function buildTextCheck(pattern) {
40
+ const escaped = pattern.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
41
+ return `document.body.textContent.includes('${escaped}')`;
42
+ }
43
+ export function registerCheck(program) {
44
+ const cmd = new Command('check')
45
+ .description('Run structured assertions against the Tauri app and exit nonzero on failure')
46
+ .option('--selector <css>', 'Assert that a CSS selector matches an element')
47
+ .option('--eval <js>', 'Assert that a JavaScript expression is truthy')
48
+ .option('--text <pattern>', 'Assert that body text contains the pattern')
49
+ .option('--no-errors', 'Assert that no console.error calls occurred during --duration')
50
+ .option('--duration <ms>', 'Duration to wait for --no-errors check (ms)', parseInt, 3000)
51
+ .option('--json', 'Output results as JSON');
52
+ addBridgeOptions(cmd);
53
+ cmd.action(async (opts) => {
54
+ const bridge = await resolveBridge(opts);
55
+ const checks = [];
56
+ // Selector check
57
+ if (opts.selector !== undefined) {
58
+ try {
59
+ const js = buildSelectorCheck(opts.selector);
60
+ const result = await bridge.eval(js);
61
+ checks.push({
62
+ type: 'selector',
63
+ passed: result === true || result === 'true',
64
+ selector: opts.selector,
65
+ });
66
+ }
67
+ catch (err) {
68
+ checks.push({
69
+ type: 'selector',
70
+ passed: false,
71
+ selector: opts.selector,
72
+ error: err instanceof Error ? err.message : String(err),
73
+ });
74
+ }
75
+ }
76
+ // Eval check
77
+ if (opts.eval !== undefined) {
78
+ try {
79
+ const js = buildEvalCheck(opts.eval);
80
+ const result = await bridge.eval(js);
81
+ checks.push({
82
+ type: 'eval',
83
+ passed: result === true || result === 'true',
84
+ expression: opts.eval,
85
+ });
86
+ }
87
+ catch (err) {
88
+ checks.push({
89
+ type: 'eval',
90
+ passed: false,
91
+ expression: opts.eval,
92
+ error: err instanceof Error ? err.message : String(err),
93
+ });
94
+ }
95
+ }
96
+ // Text check
97
+ if (opts.text !== undefined) {
98
+ try {
99
+ const js = buildTextCheck(opts.text);
100
+ const result = await bridge.eval(js);
101
+ checks.push({
102
+ type: 'text',
103
+ passed: result === true || result === 'true',
104
+ pattern: opts.text,
105
+ });
106
+ }
107
+ catch (err) {
108
+ checks.push({
109
+ type: 'text',
110
+ passed: false,
111
+ pattern: opts.text,
112
+ error: err instanceof Error ? err.message : String(err),
113
+ });
114
+ }
115
+ }
116
+ // No-errors check (opts.errors === false when --no-errors is passed)
117
+ if (opts.errors === false) {
118
+ try {
119
+ await bridge.eval(ERROR_PATCH_SCRIPT);
120
+ await new Promise((resolve) => setTimeout(resolve, opts.duration));
121
+ const raw = await bridge.eval(ERROR_DRAIN_SCRIPT);
122
+ await bridge.eval(ERROR_CLEANUP_SCRIPT).catch(() => {
123
+ // Best-effort cleanup
124
+ });
125
+ const errors = JSON.parse(String(raw));
126
+ checks.push({
127
+ type: 'no-errors',
128
+ passed: errors.length === 0,
129
+ errors,
130
+ });
131
+ }
132
+ catch (err) {
133
+ checks.push({
134
+ type: 'no-errors',
135
+ passed: false,
136
+ errors: [],
137
+ error: err instanceof Error ? err.message : String(err),
138
+ });
139
+ }
140
+ }
141
+ const passed = checks.every((c) => c.passed);
142
+ if (opts.json) {
143
+ console.log(JSON.stringify({ passed, checks }));
144
+ }
145
+ else {
146
+ for (const check of checks) {
147
+ const status = check.passed ? '[PASS]' : '[FAIL]';
148
+ if (check.type === 'selector') {
149
+ console.log(`${status} selector: ${check.selector ?? ''}`);
150
+ }
151
+ else if (check.type === 'eval') {
152
+ console.log(`${status} eval: ${check.expression ?? ''}`);
153
+ }
154
+ else if (check.type === 'text') {
155
+ console.log(`${status} text: ${check.pattern ?? ''}`);
156
+ }
157
+ else if (check.type === 'no-errors') {
158
+ const detail = !check.passed && check.errors && check.errors.length > 0
159
+ ? ` (${check.errors.length} error(s))`
160
+ : '';
161
+ console.log(`${status} no-errors${detail}`);
162
+ }
163
+ if (!check.passed && check.error) {
164
+ console.error(` error: ${check.error}`);
165
+ }
166
+ }
167
+ }
168
+ if (!passed) {
169
+ process.exitCode = 1;
170
+ }
171
+ });
172
+ program.addCommand(cmd);
173
+ }
174
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerConfigInspect(program: Command): void;