@su-record/vibe 2.7.10 → 2.7.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +37 -37
- package/CLAUDE.md +126 -222
- package/LICENSE +21 -21
- package/README.md +580 -580
- package/agents/architect-low.md +41 -41
- package/agents/architect-medium.md +59 -59
- package/agents/architect.md +80 -80
- package/agents/build-error-resolver.md +115 -115
- package/agents/compounder.md +261 -261
- package/agents/diagrammer.md +178 -178
- package/agents/docs/api-documenter.md +99 -99
- package/agents/docs/changelog-writer.md +93 -93
- package/agents/e2e-tester.md +266 -266
- package/agents/explorer-low.md +42 -42
- package/agents/explorer-medium.md +59 -59
- package/agents/explorer.md +48 -48
- package/agents/implementer-low.md +43 -43
- package/agents/implementer-medium.md +52 -52
- package/agents/implementer.md +54 -54
- package/agents/junior-mentor.md +141 -141
- package/agents/planning/requirements-analyst.md +84 -84
- package/agents/planning/ux-advisor.md +83 -83
- package/agents/qa/acceptance-tester.md +86 -86
- package/agents/qa/edge-case-finder.md +93 -93
- package/agents/refactor-cleaner.md +143 -143
- package/agents/research/best-practices-agent.md +199 -199
- package/agents/research/codebase-patterns-agent.md +157 -157
- package/agents/research/framework-docs-agent.md +188 -188
- package/agents/research/security-advisory-agent.md +213 -213
- package/agents/review/architecture-reviewer.md +107 -107
- package/agents/review/complexity-reviewer.md +116 -116
- package/agents/review/data-integrity-reviewer.md +88 -88
- package/agents/review/git-history-reviewer.md +103 -103
- package/agents/review/performance-reviewer.md +86 -86
- package/agents/review/python-reviewer.md +150 -150
- package/agents/review/rails-reviewer.md +139 -139
- package/agents/review/react-reviewer.md +144 -144
- package/agents/review/security-reviewer.md +80 -80
- package/agents/review/simplicity-reviewer.md +140 -140
- package/agents/review/test-coverage-reviewer.md +116 -116
- package/agents/review/typescript-reviewer.md +127 -127
- package/agents/searcher.md +54 -54
- package/agents/simplifier.md +120 -120
- package/agents/tester.md +49 -49
- package/agents/ui/ui-a11y-auditor.md +93 -93
- package/agents/ui/ui-antipattern-detector.md +94 -94
- package/agents/ui/ui-dataviz-advisor.md +69 -69
- package/agents/ui/ui-design-system-gen.md +57 -57
- package/agents/ui/ui-industry-analyzer.md +49 -49
- package/agents/ui/ui-layout-architect.md +65 -65
- package/agents/ui/ui-stack-implementer.md +68 -68
- package/agents/ui/ux-compliance-reviewer.md +81 -81
- package/agents/ui-previewer.md +260 -260
- package/commands/vibe.run.md +83 -0
- package/commands/vibe.spec.review.md +558 -558
- package/commands/vibe.utils.md +413 -413
- package/commands/vibe.voice.md +79 -79
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.d.ts.map +1 -1
- package/dist/cli/auth.js +15 -7
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/collaborator.js +52 -52
- package/dist/cli/commands/evolution.js +12 -12
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +62 -56
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +9 -6
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/remove.js +14 -14
- package/dist/cli/commands/sentinel.js +27 -27
- package/dist/cli/commands/skills.d.ts +13 -0
- package/dist/cli/commands/skills.d.ts.map +1 -0
- package/dist/cli/commands/skills.js +83 -0
- package/dist/cli/commands/skills.js.map +1 -0
- package/dist/cli/commands/slack.js +10 -10
- package/dist/cli/commands/telegram.js +12 -12
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +3 -0
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/detect.js +32 -32
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +64 -47
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/llm/claude-commands.js +16 -16
- package/dist/cli/llm/config.js +18 -18
- package/dist/cli/llm/gemini-commands.js +47 -47
- package/dist/cli/llm/gpt-commands.js +19 -19
- package/dist/cli/llm/help.js +21 -21
- package/dist/cli/postinstall/constants.d.ts +8 -0
- package/dist/cli/postinstall/constants.d.ts.map +1 -1
- package/dist/cli/postinstall/constants.js +33 -0
- package/dist/cli/postinstall/constants.js.map +1 -1
- package/dist/cli/postinstall/cursor-agents.js +32 -32
- package/dist/cli/postinstall/cursor-rules.js +83 -83
- package/dist/cli/postinstall/cursor-skills.js +743 -743
- package/dist/cli/postinstall/index.d.ts +1 -1
- package/dist/cli/postinstall/index.d.ts.map +1 -1
- package/dist/cli/postinstall/index.js +1 -1
- package/dist/cli/postinstall/index.js.map +1 -1
- package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
- package/dist/cli/setup/ProjectSetup.js +5 -0
- package/dist/cli/setup/ProjectSetup.js.map +1 -1
- package/dist/cli/setup/Provisioner.js +42 -42
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/infra/lib/DeepInit.js +24 -24
- package/dist/infra/lib/IterationTracker.js +11 -11
- package/dist/infra/lib/PythonParser.js +108 -108
- package/dist/infra/lib/ReviewRace.js +96 -96
- package/dist/infra/lib/SkillFrontmatter.js +28 -28
- package/dist/infra/lib/SkillQualityGate.js +9 -9
- package/dist/infra/lib/SkillRepository.js +159 -159
- package/dist/infra/lib/UltraQA.js +99 -99
- package/dist/infra/lib/autonomy/AuditStore.js +41 -41
- package/dist/infra/lib/autonomy/ConfirmationStore.js +30 -30
- package/dist/infra/lib/autonomy/EventOutbox.js +38 -38
- package/dist/infra/lib/autonomy/PolicyEngine.js +18 -18
- package/dist/infra/lib/autonomy/SecuritySentinel.js +1 -1
- package/dist/infra/lib/autonomy/SuggestionStore.js +33 -33
- package/dist/infra/lib/embedding/VectorStore.js +22 -22
- package/dist/infra/lib/evolution/AgentAnalyzer.js +10 -10
- package/dist/infra/lib/evolution/DescriptionOptimizer.d.ts +79 -0
- package/dist/infra/lib/evolution/DescriptionOptimizer.d.ts.map +1 -0
- package/dist/infra/lib/evolution/DescriptionOptimizer.js +259 -0
- package/dist/infra/lib/evolution/DescriptionOptimizer.js.map +1 -0
- package/dist/infra/lib/evolution/GenerationRegistry.js +36 -36
- package/dist/infra/lib/evolution/InsightStore.js +90 -90
- package/dist/infra/lib/evolution/RollbackManager.js +5 -5
- package/dist/infra/lib/evolution/SkillBenchmark.d.ts +81 -0
- package/dist/infra/lib/evolution/SkillBenchmark.d.ts.map +1 -0
- package/dist/infra/lib/evolution/SkillBenchmark.js +233 -0
- package/dist/infra/lib/evolution/SkillBenchmark.js.map +1 -0
- package/dist/infra/lib/evolution/SkillClassifier.d.ts +35 -0
- package/dist/infra/lib/evolution/SkillClassifier.d.ts.map +1 -0
- package/dist/infra/lib/evolution/SkillClassifier.js +167 -0
- package/dist/infra/lib/evolution/SkillClassifier.js.map +1 -0
- package/dist/infra/lib/evolution/SkillEvalRunner.d.ts +102 -0
- package/dist/infra/lib/evolution/SkillEvalRunner.d.ts.map +1 -0
- package/dist/infra/lib/evolution/SkillEvalRunner.js +256 -0
- package/dist/infra/lib/evolution/SkillEvalRunner.js.map +1 -0
- package/dist/infra/lib/evolution/SkillGapDetector.js +10 -10
- package/dist/infra/lib/evolution/UsageTracker.js +28 -28
- package/dist/infra/lib/evolution/__tests__/eval.test.d.ts +2 -0
- package/dist/infra/lib/evolution/__tests__/eval.test.d.ts.map +1 -0
- package/dist/infra/lib/evolution/__tests__/eval.test.js +539 -0
- package/dist/infra/lib/evolution/__tests__/eval.test.js.map +1 -0
- package/dist/infra/lib/evolution/index.d.ts +8 -0
- package/dist/infra/lib/evolution/index.d.ts.map +1 -1
- package/dist/infra/lib/evolution/index.js +5 -0
- package/dist/infra/lib/evolution/index.js.map +1 -1
- package/dist/infra/lib/gemini/constants.js +14 -14
- package/dist/infra/lib/gemini/orchestration.js +5 -5
- package/dist/infra/lib/gpt/oauth.js +44 -44
- package/dist/infra/lib/gpt/orchestration.js +4 -4
- package/dist/infra/lib/memory/KnowledgeGraph.js +4 -4
- package/dist/infra/lib/memory/MemorySearch.js +57 -57
- package/dist/infra/lib/memory/MemoryStorage.js +181 -181
- package/dist/infra/lib/memory/ObservationStore.js +28 -28
- package/dist/infra/lib/memory/ReflectionStore.js +30 -30
- package/dist/infra/lib/memory/SessionRAGRetriever.js +7 -7
- package/dist/infra/lib/memory/SessionRAGStore.js +225 -225
- package/dist/infra/lib/memory/SessionSummarizer.js +9 -9
- package/dist/infra/orchestrator/AgentManager.js +12 -12
- package/dist/infra/orchestrator/AgentRegistry.js +65 -65
- package/dist/infra/orchestrator/MultiLlmResearch.js +8 -8
- package/dist/infra/orchestrator/SwarmOrchestrator.test.js +16 -16
- package/dist/infra/orchestrator/parallelResearch.js +24 -24
- package/dist/tools/convention/analyzeComplexity.test.js +115 -115
- package/dist/tools/convention/validateCodeQuality.test.js +104 -104
- package/dist/tools/memory/createMemoryTimeline.js +10 -10
- package/dist/tools/memory/getMemoryGraph.js +12 -12
- package/dist/tools/memory/getSessionContext.js +9 -9
- package/dist/tools/memory/linkMemories.js +14 -14
- package/dist/tools/memory/listMemories.js +4 -4
- package/dist/tools/memory/recallMemory.js +4 -4
- package/dist/tools/memory/saveMemory.js +4 -4
- package/dist/tools/memory/searchMemoriesAdvanced.js +23 -23
- package/dist/tools/semantic/analyzeDependencyGraph.js +12 -12
- package/dist/tools/semantic/astGrep.test.js +6 -6
- package/dist/tools/spec/prdParser.test.js +171 -171
- package/dist/tools/spec/specGenerator.js +169 -169
- package/dist/tools/spec/traceabilityMatrix.js +64 -64
- package/dist/tools/spec/traceabilityMatrix.test.js +28 -28
- package/hooks/gemini-hooks.json +73 -73
- package/hooks/hooks.json +137 -137
- package/hooks/scripts/code-check.js +70 -70
- package/hooks/scripts/context-save.js +212 -212
- package/hooks/scripts/hud-status.js +291 -291
- package/hooks/scripts/keyword-detector.js +214 -214
- package/hooks/scripts/llm-orchestrate.js +646 -646
- package/hooks/scripts/post-edit.js +32 -32
- package/hooks/scripts/pre-tool-guard.js +125 -125
- package/hooks/scripts/prompt-dispatcher.js +185 -185
- package/hooks/scripts/sentinel-guard.js +104 -104
- package/hooks/scripts/session-start.js +106 -106
- package/hooks/scripts/stop-notify.js +209 -209
- package/hooks/scripts/utils.js +100 -100
- package/languages/csharp-unity.md +515 -515
- package/languages/gdscript-godot.md +470 -470
- package/languages/ruby-rails.md +489 -489
- package/languages/typescript-angular.md +433 -433
- package/languages/typescript-astro.md +416 -416
- package/languages/typescript-electron.md +406 -406
- package/languages/typescript-nestjs.md +524 -524
- package/languages/typescript-svelte.md +407 -407
- package/languages/typescript-tauri.md +365 -365
- package/package.json +121 -121
- package/skills/agents-md/SKILL.md +120 -120
- package/skills/arch-guard/SKILL.md +180 -0
- package/skills/brand-assets/SKILL.md +146 -146
- package/skills/capability-loop/SKILL.md +167 -0
- package/skills/characterization-test/SKILL.md +206 -206
- package/skills/commerce-patterns/SKILL.md +59 -59
- package/skills/commit-push-pr/SKILL.md +75 -75
- package/skills/context7-usage/SKILL.md +105 -105
- package/skills/core-capabilities/SKILL.md +48 -48
- package/skills/e2e-commerce/SKILL.md +57 -57
- package/skills/exec-plan/SKILL.md +147 -0
- package/skills/frontend-design/SKILL.md +73 -73
- package/skills/git-worktree/SKILL.md +72 -72
- package/skills/handoff/SKILL.md +109 -109
- package/skills/parallel-research/SKILL.md +87 -87
- package/skills/priority-todos/SKILL.md +63 -63
- package/skills/seo-checklist/SKILL.md +57 -57
- package/skills/techdebt/SKILL.md +122 -122
- package/skills/tool-fallback/SKILL.md +103 -103
- package/skills/typescript-advanced-types/SKILL.md +65 -65
- package/skills/ui-ux-pro-max/SKILL.md +206 -206
- package/skills/vercel-react-best-practices/SKILL.md +59 -59
- package/skills/video-production/SKILL.md +51 -51
- package/vibe/config.json +29 -29
- package/vibe/constitution.md +227 -227
- package/vibe/rules/principles/communication-guide.md +98 -98
- package/vibe/rules/principles/development-philosophy.md +52 -52
- package/vibe/rules/principles/quick-start.md +102 -102
- package/vibe/rules/quality/bdd-contract-testing.md +393 -393
- package/vibe/rules/quality/checklist.md +276 -276
- package/vibe/rules/quality/performance.md +236 -236
- package/vibe/rules/quality/testing-strategy.md +440 -440
- package/vibe/rules/standards/anti-patterns.md +541 -541
- package/vibe/rules/standards/code-structure.md +291 -291
- package/vibe/rules/standards/complexity-metrics.md +313 -313
- package/vibe/rules/standards/git-workflow.md +237 -237
- package/vibe/rules/standards/naming-conventions.md +198 -198
- package/vibe/rules/standards/security.md +305 -305
- package/vibe/rules/writing/document-style.md +74 -74
- package/vibe/setup.sh +31 -31
- package/vibe/templates/constitution-template.md +252 -252
- package/vibe/templates/contract-backend-template.md +526 -526
- package/vibe/templates/contract-frontend-template.md +599 -599
- package/vibe/templates/feature-template.md +96 -96
- package/vibe/templates/spec-template.md +221 -221
- package/vibe/ui-ux-data/charts.csv +26 -26
- package/vibe/ui-ux-data/colors.csv +97 -97
- package/vibe/ui-ux-data/icons.csv +101 -101
- package/vibe/ui-ux-data/landing.csv +31 -31
- package/vibe/ui-ux-data/products.csv +96 -96
- package/vibe/ui-ux-data/react-performance.csv +45 -45
- package/vibe/ui-ux-data/stacks/astro.csv +54 -54
- package/vibe/ui-ux-data/stacks/flutter.csv +53 -53
- package/vibe/ui-ux-data/stacks/html-tailwind.csv +56 -56
- package/vibe/ui-ux-data/stacks/jetpack-compose.csv +53 -53
- package/vibe/ui-ux-data/stacks/nextjs.csv +53 -53
- package/vibe/ui-ux-data/stacks/nuxt-ui.csv +51 -51
- package/vibe/ui-ux-data/stacks/nuxtjs.csv +59 -59
- package/vibe/ui-ux-data/stacks/react-native.csv +52 -52
- package/vibe/ui-ux-data/stacks/react.csv +54 -54
- package/vibe/ui-ux-data/stacks/shadcn.csv +61 -61
- package/vibe/ui-ux-data/stacks/svelte.csv +54 -54
- package/vibe/ui-ux-data/stacks/swiftui.csv +51 -51
- package/vibe/ui-ux-data/stacks/vue.csv +50 -50
- package/vibe/ui-ux-data/styles.csv +68 -68
- package/vibe/ui-ux-data/typography.csv +57 -57
- package/vibe/ui-ux-data/ui-reasoning.csv +101 -101
- package/vibe/ui-ux-data/ux-guidelines.csv +99 -99
- package/vibe/ui-ux-data/version.json +31 -31
- package/vibe/ui-ux-data/web-interface.csv +31 -31
|
@@ -1,365 +1,365 @@
|
|
|
1
|
-
# TypeScript + Tauri v2 Quality Rules
|
|
2
|
-
|
|
3
|
-
## Core Principles (inherited from core)
|
|
4
|
-
|
|
5
|
-
```markdown
|
|
6
|
-
# Core Principles (inherited from core)
|
|
7
|
-
Single Responsibility (SRP)
|
|
8
|
-
No Duplication (DRY)
|
|
9
|
-
Reusability
|
|
10
|
-
Low Complexity
|
|
11
|
-
Function <= 30 lines, JSX <= 50 lines
|
|
12
|
-
Nesting <= 3 levels
|
|
13
|
-
Cyclomatic complexity <= 10
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Tauri Architecture Understanding
|
|
17
|
-
|
|
18
|
-
```text
|
|
19
|
-
Frontend (TypeScript/React/Vue/Svelte)
|
|
20
|
-
- UI rendering
|
|
21
|
-
- User interaction
|
|
22
|
-
- @tauri-apps/api calls
|
|
23
|
-
|
|
24
|
-
Tauri Core (Rust)
|
|
25
|
-
- System API access
|
|
26
|
-
- File system, network
|
|
27
|
-
- Security sandbox
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## TypeScript/Tauri Specific Rules
|
|
31
|
-
|
|
32
|
-
### 1. Tauri Command Type Safety
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
// Bad: Using any
|
|
36
|
-
const result = await invoke('get_data');
|
|
37
|
-
|
|
38
|
-
// Good: Clear type definition
|
|
39
|
-
interface FileInfo {
|
|
40
|
-
path: string;
|
|
41
|
-
size: number;
|
|
42
|
-
modified: number;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const fileInfo = await invoke<FileInfo>('get_file_info', { path: '/path/to/file' });
|
|
46
|
-
|
|
47
|
-
// Good: Command response type definition
|
|
48
|
-
interface CommandResponse<T> {
|
|
49
|
-
success: boolean;
|
|
50
|
-
data?: T;
|
|
51
|
-
error?: string;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function invokeCommand<T>(cmd: string, args?: Record<string, unknown>): Promise<T> {
|
|
55
|
-
try {
|
|
56
|
-
return await invoke<T>(cmd, args);
|
|
57
|
-
} catch (error) {
|
|
58
|
-
throw new Error(`Command ${cmd} failed: ${error}`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### 2. Tauri API Usage Patterns
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
import { invoke } from '@tauri-apps/api/core';
|
|
67
|
-
import { open, save } from '@tauri-apps/plugin-dialog';
|
|
68
|
-
import { readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
|
|
69
|
-
|
|
70
|
-
// Good: File dialog + read
|
|
71
|
-
async function openFile(): Promise<string | null> {
|
|
72
|
-
const selected = await open({
|
|
73
|
-
multiple: false,
|
|
74
|
-
filters: [{ name: 'Text', extensions: ['txt', 'md'] }]
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
if (!selected) return null;
|
|
78
|
-
|
|
79
|
-
return await readTextFile(selected as string);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Good: File save
|
|
83
|
-
async function saveFile(content: string): Promise<void> {
|
|
84
|
-
const path = await save({
|
|
85
|
-
filters: [{ name: 'Text', extensions: ['txt'] }]
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
if (path) {
|
|
89
|
-
await writeTextFile(path, content);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### 3. Event System Usage
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { listen, emit } from '@tauri-apps/api/event';
|
|
98
|
-
|
|
99
|
-
// Good: Event listener (cleanup required)
|
|
100
|
-
function useBackendEvent<T>(eventName: string, handler: (payload: T) => void) {
|
|
101
|
-
useEffect(() => {
|
|
102
|
-
const unlisten = listen<T>(eventName, (event) => {
|
|
103
|
-
handler(event.payload);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
return () => {
|
|
107
|
-
unlisten.then(fn => fn());
|
|
108
|
-
};
|
|
109
|
-
}, [eventName, handler]);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Good: Frontend -> Backend event
|
|
113
|
-
async function notifyBackend(action: string, data: unknown): Promise<void> {
|
|
114
|
-
await emit('frontend-action', { action, data });
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### 4. Window Management
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
import { getCurrentWindow } from '@tauri-apps/api/window';
|
|
122
|
-
|
|
123
|
-
// Good: Window control
|
|
124
|
-
async function setupWindow(): Promise<void> {
|
|
125
|
-
const appWindow = getCurrentWindow();
|
|
126
|
-
|
|
127
|
-
// Set window size
|
|
128
|
-
await appWindow.setSize(new LogicalSize(800, 600));
|
|
129
|
-
|
|
130
|
-
// Center window
|
|
131
|
-
await appWindow.center();
|
|
132
|
-
|
|
133
|
-
// Set window title
|
|
134
|
-
await appWindow.setTitle('My Tauri App');
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Good: Window event listener
|
|
138
|
-
function useWindowEvents() {
|
|
139
|
-
useEffect(() => {
|
|
140
|
-
const appWindow = getCurrentWindow();
|
|
141
|
-
|
|
142
|
-
const unlistenClose = appWindow.onCloseRequested(async (event) => {
|
|
143
|
-
// Check for unsaved changes
|
|
144
|
-
if (hasUnsavedChanges) {
|
|
145
|
-
event.preventDefault();
|
|
146
|
-
// Show confirmation dialog
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
return () => {
|
|
151
|
-
unlistenClose.then(fn => fn());
|
|
152
|
-
};
|
|
153
|
-
}, []);
|
|
154
|
-
}
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### 5. Rust Command Definition (Backend)
|
|
158
|
-
|
|
159
|
-
```rust
|
|
160
|
-
// src-tauri/src/main.rs or lib.rs
|
|
161
|
-
|
|
162
|
-
// Good: Command definition
|
|
163
|
-
#[tauri::command]
|
|
164
|
-
fn greet(name: &str) -> String {
|
|
165
|
-
format!("Hello, {}!", name)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Good: Async Command
|
|
169
|
-
#[tauri::command]
|
|
170
|
-
async fn read_file(path: String) -> Result<String, String> {
|
|
171
|
-
tokio::fs::read_to_string(&path)
|
|
172
|
-
.await
|
|
173
|
-
.map_err(|e| e.to_string())
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Good: Using State
|
|
177
|
-
#[tauri::command]
|
|
178
|
-
fn get_count(state: tauri::State<'_, AppState>) -> u32 {
|
|
179
|
-
*state.count.lock().unwrap()
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Register in main.rs
|
|
183
|
-
fn main() {
|
|
184
|
-
tauri::Builder::default()
|
|
185
|
-
.invoke_handler(tauri::generate_handler![greet, read_file, get_count])
|
|
186
|
-
.run(tauri::generate_context!())
|
|
187
|
-
.expect("error while running tauri application");
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### 6. Security Configuration (tauri.conf.json)
|
|
192
|
-
|
|
193
|
-
```json
|
|
194
|
-
{
|
|
195
|
-
"app": {
|
|
196
|
-
"security": {
|
|
197
|
-
"csp": "default-src 'self'; script-src 'self'"
|
|
198
|
-
}
|
|
199
|
-
},
|
|
200
|
-
"plugins": {
|
|
201
|
-
"fs": {
|
|
202
|
-
"scope": ["$APP/*", "$RESOURCE/*"]
|
|
203
|
-
},
|
|
204
|
-
"shell": {
|
|
205
|
-
"open": true,
|
|
206
|
-
"scope": []
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### 7. Custom Hook Pattern
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
// Good: Tauri Command Hook
|
|
216
|
-
function useTauriCommand<T, A extends Record<string, unknown>>(
|
|
217
|
-
command: string
|
|
218
|
-
) {
|
|
219
|
-
const [data, setData] = useState<T | null>(null);
|
|
220
|
-
const [loading, setLoading] = useState(false);
|
|
221
|
-
const [error, setError] = useState<string | null>(null);
|
|
222
|
-
|
|
223
|
-
const execute = useCallback(async (args?: A) => {
|
|
224
|
-
setLoading(true);
|
|
225
|
-
setError(null);
|
|
226
|
-
try {
|
|
227
|
-
const result = await invoke<T>(command, args);
|
|
228
|
-
setData(result);
|
|
229
|
-
return result;
|
|
230
|
-
} catch (e) {
|
|
231
|
-
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
232
|
-
setError(errorMsg);
|
|
233
|
-
throw e;
|
|
234
|
-
} finally {
|
|
235
|
-
setLoading(false);
|
|
236
|
-
}
|
|
237
|
-
}, [command]);
|
|
238
|
-
|
|
239
|
-
return { data, loading, error, execute };
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Usage example
|
|
243
|
-
function FileViewer() {
|
|
244
|
-
const { data: content, loading, error, execute } = useTauriCommand<string>('read_file');
|
|
245
|
-
|
|
246
|
-
const handleOpen = async () => {
|
|
247
|
-
await execute({ path: '/path/to/file.txt' });
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
return (
|
|
251
|
-
<div>
|
|
252
|
-
<button onClick={handleOpen} disabled={loading}>
|
|
253
|
-
{loading ? 'Loading...' : 'Open File'}
|
|
254
|
-
</button>
|
|
255
|
-
{error && <p className="error">{error}</p>}
|
|
256
|
-
{content && <pre>{content}</pre>}
|
|
257
|
-
</div>
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### 8. Build and Deploy
|
|
263
|
-
|
|
264
|
-
```bash
|
|
265
|
-
# Development mode
|
|
266
|
-
npm run tauri dev
|
|
267
|
-
|
|
268
|
-
# Production build
|
|
269
|
-
npm run tauri build
|
|
270
|
-
|
|
271
|
-
# Specific target
|
|
272
|
-
npm run tauri build -- --target x86_64-pc-windows-msvc
|
|
273
|
-
npm run tauri build -- --target aarch64-apple-darwin
|
|
274
|
-
npm run tauri build -- --target x86_64-unknown-linux-gnu
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
## Recommended Folder Structure
|
|
278
|
-
|
|
279
|
-
```text
|
|
280
|
-
my-tauri-app/
|
|
281
|
-
├── src/ # Frontend
|
|
282
|
-
│ ├── components/
|
|
283
|
-
│ ├── hooks/
|
|
284
|
-
│ │ └── useTauri.ts # Tauri hooks
|
|
285
|
-
│ ├── lib/
|
|
286
|
-
│ │ └── commands.ts # Command wrappers
|
|
287
|
-
│ └── App.tsx
|
|
288
|
-
├── src-tauri/ # Backend (Rust)
|
|
289
|
-
│ ├── src/
|
|
290
|
-
│ │ ├── main.rs
|
|
291
|
-
│ │ └── commands/ # Command modules
|
|
292
|
-
│ ├── Cargo.toml
|
|
293
|
-
│ └── tauri.conf.json
|
|
294
|
-
└── package.json
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
## Performance Optimization
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
// Good: Large data streaming
|
|
301
|
-
import { Channel } from '@tauri-apps/api/core';
|
|
302
|
-
|
|
303
|
-
async function streamLargeFile(path: string): Promise<void> {
|
|
304
|
-
const channel = new Channel<string>();
|
|
305
|
-
|
|
306
|
-
channel.onmessage = (chunk) => {
|
|
307
|
-
// Process chunk by chunk
|
|
308
|
-
appendToDisplay(chunk);
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
await invoke('stream_file', { path, channel });
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Good: Background task
|
|
315
|
-
async function runHeavyTask(): Promise<void> {
|
|
316
|
-
// Process in separate thread in Rust
|
|
317
|
-
await invoke('heavy_computation', { data: largeData });
|
|
318
|
-
}
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
## Debugging
|
|
322
|
-
|
|
323
|
-
```typescript
|
|
324
|
-
// Good: Logging only in development mode
|
|
325
|
-
const isDev = import.meta.env.DEV;
|
|
326
|
-
|
|
327
|
-
function debugLog(message: string, data?: unknown): void {
|
|
328
|
-
if (isDev) {
|
|
329
|
-
console.log(`[Tauri] ${message}`, data);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Good: Check Rust logs (in terminal)
|
|
334
|
-
// RUST_LOG=debug npm run tauri dev
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
## Testing
|
|
338
|
-
|
|
339
|
-
```typescript
|
|
340
|
-
// Good: Command Mock
|
|
341
|
-
import { mockIPC } from '@tauri-apps/api/mocks';
|
|
342
|
-
|
|
343
|
-
beforeAll(() => {
|
|
344
|
-
mockIPC((cmd, args) => {
|
|
345
|
-
if (cmd === 'greet') {
|
|
346
|
-
return `Hello, ${args.name}!`;
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
test('greet command', async () => {
|
|
352
|
-
const result = await invoke('greet', { name: 'World' });
|
|
353
|
-
expect(result).toBe('Hello, World!');
|
|
354
|
-
});
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
## Checklist
|
|
358
|
-
|
|
359
|
-
- [ ] Define types for all Commands
|
|
360
|
-
- [ ] Handle event listener cleanup
|
|
361
|
-
- [ ] Minimize file access scope (tauri.conf.json)
|
|
362
|
-
- [ ] Verify CSP configuration
|
|
363
|
-
- [ ] Error handling (Rust -> Frontend)
|
|
364
|
-
- [ ] Handle large data streaming
|
|
365
|
-
- [ ] Separate development/production environments
|
|
1
|
+
# TypeScript + Tauri v2 Quality Rules
|
|
2
|
+
|
|
3
|
+
## Core Principles (inherited from core)
|
|
4
|
+
|
|
5
|
+
```markdown
|
|
6
|
+
# Core Principles (inherited from core)
|
|
7
|
+
Single Responsibility (SRP)
|
|
8
|
+
No Duplication (DRY)
|
|
9
|
+
Reusability
|
|
10
|
+
Low Complexity
|
|
11
|
+
Function <= 30 lines, JSX <= 50 lines
|
|
12
|
+
Nesting <= 3 levels
|
|
13
|
+
Cyclomatic complexity <= 10
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Tauri Architecture Understanding
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
Frontend (TypeScript/React/Vue/Svelte)
|
|
20
|
+
- UI rendering
|
|
21
|
+
- User interaction
|
|
22
|
+
- @tauri-apps/api calls
|
|
23
|
+
|
|
24
|
+
Tauri Core (Rust)
|
|
25
|
+
- System API access
|
|
26
|
+
- File system, network
|
|
27
|
+
- Security sandbox
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## TypeScript/Tauri Specific Rules
|
|
31
|
+
|
|
32
|
+
### 1. Tauri Command Type Safety
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// Bad: Using any
|
|
36
|
+
const result = await invoke('get_data');
|
|
37
|
+
|
|
38
|
+
// Good: Clear type definition
|
|
39
|
+
interface FileInfo {
|
|
40
|
+
path: string;
|
|
41
|
+
size: number;
|
|
42
|
+
modified: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const fileInfo = await invoke<FileInfo>('get_file_info', { path: '/path/to/file' });
|
|
46
|
+
|
|
47
|
+
// Good: Command response type definition
|
|
48
|
+
interface CommandResponse<T> {
|
|
49
|
+
success: boolean;
|
|
50
|
+
data?: T;
|
|
51
|
+
error?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function invokeCommand<T>(cmd: string, args?: Record<string, unknown>): Promise<T> {
|
|
55
|
+
try {
|
|
56
|
+
return await invoke<T>(cmd, args);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
throw new Error(`Command ${cmd} failed: ${error}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2. Tauri API Usage Patterns
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { invoke } from '@tauri-apps/api/core';
|
|
67
|
+
import { open, save } from '@tauri-apps/plugin-dialog';
|
|
68
|
+
import { readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
|
|
69
|
+
|
|
70
|
+
// Good: File dialog + read
|
|
71
|
+
async function openFile(): Promise<string | null> {
|
|
72
|
+
const selected = await open({
|
|
73
|
+
multiple: false,
|
|
74
|
+
filters: [{ name: 'Text', extensions: ['txt', 'md'] }]
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
if (!selected) return null;
|
|
78
|
+
|
|
79
|
+
return await readTextFile(selected as string);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Good: File save
|
|
83
|
+
async function saveFile(content: string): Promise<void> {
|
|
84
|
+
const path = await save({
|
|
85
|
+
filters: [{ name: 'Text', extensions: ['txt'] }]
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (path) {
|
|
89
|
+
await writeTextFile(path, content);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 3. Event System Usage
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { listen, emit } from '@tauri-apps/api/event';
|
|
98
|
+
|
|
99
|
+
// Good: Event listener (cleanup required)
|
|
100
|
+
function useBackendEvent<T>(eventName: string, handler: (payload: T) => void) {
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
const unlisten = listen<T>(eventName, (event) => {
|
|
103
|
+
handler(event.payload);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return () => {
|
|
107
|
+
unlisten.then(fn => fn());
|
|
108
|
+
};
|
|
109
|
+
}, [eventName, handler]);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Good: Frontend -> Backend event
|
|
113
|
+
async function notifyBackend(action: string, data: unknown): Promise<void> {
|
|
114
|
+
await emit('frontend-action', { action, data });
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 4. Window Management
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import { getCurrentWindow } from '@tauri-apps/api/window';
|
|
122
|
+
|
|
123
|
+
// Good: Window control
|
|
124
|
+
async function setupWindow(): Promise<void> {
|
|
125
|
+
const appWindow = getCurrentWindow();
|
|
126
|
+
|
|
127
|
+
// Set window size
|
|
128
|
+
await appWindow.setSize(new LogicalSize(800, 600));
|
|
129
|
+
|
|
130
|
+
// Center window
|
|
131
|
+
await appWindow.center();
|
|
132
|
+
|
|
133
|
+
// Set window title
|
|
134
|
+
await appWindow.setTitle('My Tauri App');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Good: Window event listener
|
|
138
|
+
function useWindowEvents() {
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
const appWindow = getCurrentWindow();
|
|
141
|
+
|
|
142
|
+
const unlistenClose = appWindow.onCloseRequested(async (event) => {
|
|
143
|
+
// Check for unsaved changes
|
|
144
|
+
if (hasUnsavedChanges) {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
// Show confirmation dialog
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
return () => {
|
|
151
|
+
unlistenClose.then(fn => fn());
|
|
152
|
+
};
|
|
153
|
+
}, []);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 5. Rust Command Definition (Backend)
|
|
158
|
+
|
|
159
|
+
```rust
|
|
160
|
+
// src-tauri/src/main.rs or lib.rs
|
|
161
|
+
|
|
162
|
+
// Good: Command definition
|
|
163
|
+
#[tauri::command]
|
|
164
|
+
fn greet(name: &str) -> String {
|
|
165
|
+
format!("Hello, {}!", name)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Good: Async Command
|
|
169
|
+
#[tauri::command]
|
|
170
|
+
async fn read_file(path: String) -> Result<String, String> {
|
|
171
|
+
tokio::fs::read_to_string(&path)
|
|
172
|
+
.await
|
|
173
|
+
.map_err(|e| e.to_string())
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Good: Using State
|
|
177
|
+
#[tauri::command]
|
|
178
|
+
fn get_count(state: tauri::State<'_, AppState>) -> u32 {
|
|
179
|
+
*state.count.lock().unwrap()
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Register in main.rs
|
|
183
|
+
fn main() {
|
|
184
|
+
tauri::Builder::default()
|
|
185
|
+
.invoke_handler(tauri::generate_handler![greet, read_file, get_count])
|
|
186
|
+
.run(tauri::generate_context!())
|
|
187
|
+
.expect("error while running tauri application");
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 6. Security Configuration (tauri.conf.json)
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"app": {
|
|
196
|
+
"security": {
|
|
197
|
+
"csp": "default-src 'self'; script-src 'self'"
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
"plugins": {
|
|
201
|
+
"fs": {
|
|
202
|
+
"scope": ["$APP/*", "$RESOURCE/*"]
|
|
203
|
+
},
|
|
204
|
+
"shell": {
|
|
205
|
+
"open": true,
|
|
206
|
+
"scope": []
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 7. Custom Hook Pattern
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
// Good: Tauri Command Hook
|
|
216
|
+
function useTauriCommand<T, A extends Record<string, unknown>>(
|
|
217
|
+
command: string
|
|
218
|
+
) {
|
|
219
|
+
const [data, setData] = useState<T | null>(null);
|
|
220
|
+
const [loading, setLoading] = useState(false);
|
|
221
|
+
const [error, setError] = useState<string | null>(null);
|
|
222
|
+
|
|
223
|
+
const execute = useCallback(async (args?: A) => {
|
|
224
|
+
setLoading(true);
|
|
225
|
+
setError(null);
|
|
226
|
+
try {
|
|
227
|
+
const result = await invoke<T>(command, args);
|
|
228
|
+
setData(result);
|
|
229
|
+
return result;
|
|
230
|
+
} catch (e) {
|
|
231
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
232
|
+
setError(errorMsg);
|
|
233
|
+
throw e;
|
|
234
|
+
} finally {
|
|
235
|
+
setLoading(false);
|
|
236
|
+
}
|
|
237
|
+
}, [command]);
|
|
238
|
+
|
|
239
|
+
return { data, loading, error, execute };
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Usage example
|
|
243
|
+
function FileViewer() {
|
|
244
|
+
const { data: content, loading, error, execute } = useTauriCommand<string>('read_file');
|
|
245
|
+
|
|
246
|
+
const handleOpen = async () => {
|
|
247
|
+
await execute({ path: '/path/to/file.txt' });
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
return (
|
|
251
|
+
<div>
|
|
252
|
+
<button onClick={handleOpen} disabled={loading}>
|
|
253
|
+
{loading ? 'Loading...' : 'Open File'}
|
|
254
|
+
</button>
|
|
255
|
+
{error && <p className="error">{error}</p>}
|
|
256
|
+
{content && <pre>{content}</pre>}
|
|
257
|
+
</div>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### 8. Build and Deploy
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Development mode
|
|
266
|
+
npm run tauri dev
|
|
267
|
+
|
|
268
|
+
# Production build
|
|
269
|
+
npm run tauri build
|
|
270
|
+
|
|
271
|
+
# Specific target
|
|
272
|
+
npm run tauri build -- --target x86_64-pc-windows-msvc
|
|
273
|
+
npm run tauri build -- --target aarch64-apple-darwin
|
|
274
|
+
npm run tauri build -- --target x86_64-unknown-linux-gnu
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Recommended Folder Structure
|
|
278
|
+
|
|
279
|
+
```text
|
|
280
|
+
my-tauri-app/
|
|
281
|
+
├── src/ # Frontend
|
|
282
|
+
│ ├── components/
|
|
283
|
+
│ ├── hooks/
|
|
284
|
+
│ │ └── useTauri.ts # Tauri hooks
|
|
285
|
+
│ ├── lib/
|
|
286
|
+
│ │ └── commands.ts # Command wrappers
|
|
287
|
+
│ └── App.tsx
|
|
288
|
+
├── src-tauri/ # Backend (Rust)
|
|
289
|
+
│ ├── src/
|
|
290
|
+
│ │ ├── main.rs
|
|
291
|
+
│ │ └── commands/ # Command modules
|
|
292
|
+
│ ├── Cargo.toml
|
|
293
|
+
│ └── tauri.conf.json
|
|
294
|
+
└── package.json
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Performance Optimization
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
// Good: Large data streaming
|
|
301
|
+
import { Channel } from '@tauri-apps/api/core';
|
|
302
|
+
|
|
303
|
+
async function streamLargeFile(path: string): Promise<void> {
|
|
304
|
+
const channel = new Channel<string>();
|
|
305
|
+
|
|
306
|
+
channel.onmessage = (chunk) => {
|
|
307
|
+
// Process chunk by chunk
|
|
308
|
+
appendToDisplay(chunk);
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
await invoke('stream_file', { path, channel });
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Good: Background task
|
|
315
|
+
async function runHeavyTask(): Promise<void> {
|
|
316
|
+
// Process in separate thread in Rust
|
|
317
|
+
await invoke('heavy_computation', { data: largeData });
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Debugging
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
// Good: Logging only in development mode
|
|
325
|
+
const isDev = import.meta.env.DEV;
|
|
326
|
+
|
|
327
|
+
function debugLog(message: string, data?: unknown): void {
|
|
328
|
+
if (isDev) {
|
|
329
|
+
console.log(`[Tauri] ${message}`, data);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Good: Check Rust logs (in terminal)
|
|
334
|
+
// RUST_LOG=debug npm run tauri dev
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Testing
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
// Good: Command Mock
|
|
341
|
+
import { mockIPC } from '@tauri-apps/api/mocks';
|
|
342
|
+
|
|
343
|
+
beforeAll(() => {
|
|
344
|
+
mockIPC((cmd, args) => {
|
|
345
|
+
if (cmd === 'greet') {
|
|
346
|
+
return `Hello, ${args.name}!`;
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test('greet command', async () => {
|
|
352
|
+
const result = await invoke('greet', { name: 'World' });
|
|
353
|
+
expect(result).toBe('Hello, World!');
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Checklist
|
|
358
|
+
|
|
359
|
+
- [ ] Define types for all Commands
|
|
360
|
+
- [ ] Handle event listener cleanup
|
|
361
|
+
- [ ] Minimize file access scope (tauri.conf.json)
|
|
362
|
+
- [ ] Verify CSP configuration
|
|
363
|
+
- [ ] Error handling (Rust -> Frontend)
|
|
364
|
+
- [ ] Handle large data streaming
|
|
365
|
+
- [ ] Separate development/production environments
|