claude-mpm 5.4.55__py3-none-any.whl → 5.4.85__py3-none-any.whl
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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md +405 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +63 -241
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
- claude_mpm/agents/PM_INSTRUCTIONS.md +36 -9
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agents.py +2 -4
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/skills.py +166 -14
- claude_mpm/cli/executor.py +1 -0
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +30 -50
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +5 -0
- claude_mpm/cli/startup.py +223 -388
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +2 -2
- claude_mpm/core/interactive_session.py +7 -7
- claude_mpm/core/output_style_manager.py +21 -13
- claude_mpm/core/unified_config.py +50 -8
- claude_mpm/core/unified_paths.py +30 -13
- claude_mpm/scripts/start_activity_logging.py +0 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +8 -0
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +7 -4
- claude_mpm/services/agents/startup_sync.py +5 -2
- claude_mpm/services/pm_skills_deployer.py +4 -0
- claude_mpm/services/skills/git_skill_source_manager.py +24 -8
- claude_mpm/services/skills/selective_skill_deployer.py +82 -83
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/pm-bug-reporting/pm-bug-reporting.md +248 -0
- claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/pm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/utils/agent_dependency_loader.py +103 -4
- claude_mpm/utils/robust_installer.py +45 -24
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/METADATA +47 -23
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/RECORD +159 -47
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tauri-command-patterns
|
|
3
|
+
description: Advanced Tauri command patterns including complex parameters, special injected parameters, struct handling, and command organization
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
category: development
|
|
6
|
+
author: Claude MPM Team
|
|
7
|
+
license: MIT
|
|
8
|
+
progressive_disclosure:
|
|
9
|
+
entry_point:
|
|
10
|
+
summary: "Advanced command patterns for Tauri: complex parameters, special injections, struct handling, and modular organization"
|
|
11
|
+
when_to_use: "When commands need complex data structures, multiple special parameters, or organized command modules"
|
|
12
|
+
quick_start: "1. Define struct with serde::Deserialize 2. Use special parameters (State/Window/AppHandle) 3. Organize commands in modules 4. Handle optional parameters"
|
|
13
|
+
context_limit: 600
|
|
14
|
+
tags:
|
|
15
|
+
- tauri
|
|
16
|
+
- commands
|
|
17
|
+
- ipc
|
|
18
|
+
- parameters
|
|
19
|
+
- rust
|
|
20
|
+
requires_tools: []
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Tauri Advanced Command Patterns
|
|
24
|
+
|
|
25
|
+
## Complex Parameter Handling
|
|
26
|
+
|
|
27
|
+
### Struct Parameters
|
|
28
|
+
|
|
29
|
+
Commands can accept complex data structures that automatically deserialize from JSON:
|
|
30
|
+
|
|
31
|
+
```rust
|
|
32
|
+
use serde::Deserialize;
|
|
33
|
+
|
|
34
|
+
#[derive(Deserialize)]
|
|
35
|
+
struct UserInput {
|
|
36
|
+
name: String,
|
|
37
|
+
email: String,
|
|
38
|
+
age: Option<u32>,
|
|
39
|
+
preferences: Vec<String>,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#[tauri::command]
|
|
43
|
+
async fn create_user(input: UserInput) -> Result<String, String> {
|
|
44
|
+
// Validate
|
|
45
|
+
if input.name.is_empty() {
|
|
46
|
+
return Err("Name cannot be empty".to_string());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Process
|
|
50
|
+
let user_id = save_user(&input).await?;
|
|
51
|
+
|
|
52
|
+
Ok(format!("User created with ID: {}", user_id))
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Frontend usage**:
|
|
57
|
+
```typescript
|
|
58
|
+
const result = await invoke<string>('create_user', {
|
|
59
|
+
input: {
|
|
60
|
+
name: 'John Doe',
|
|
61
|
+
email: 'john@example.com',
|
|
62
|
+
age: 30,
|
|
63
|
+
preferences: ['dark-mode', 'notifications']
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Nested Structures
|
|
69
|
+
|
|
70
|
+
```rust
|
|
71
|
+
#[derive(Deserialize)]
|
|
72
|
+
struct Address {
|
|
73
|
+
street: String,
|
|
74
|
+
city: String,
|
|
75
|
+
zip: String,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
#[derive(Deserialize)]
|
|
79
|
+
struct UserProfile {
|
|
80
|
+
name: String,
|
|
81
|
+
email: String,
|
|
82
|
+
address: Address,
|
|
83
|
+
tags: HashMap<String, String>,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#[tauri::command]
|
|
87
|
+
async fn update_profile(profile: UserProfile) -> Result<(), String> {
|
|
88
|
+
// Full nested structure automatically deserialized
|
|
89
|
+
validate_address(&profile.address)?;
|
|
90
|
+
save_profile(profile).await
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Optional Parameters
|
|
95
|
+
|
|
96
|
+
```rust
|
|
97
|
+
#[tauri::command]
|
|
98
|
+
async fn search_users(
|
|
99
|
+
query: String,
|
|
100
|
+
limit: Option<usize>,
|
|
101
|
+
offset: Option<usize>,
|
|
102
|
+
) -> Result<Vec<User>, String> {
|
|
103
|
+
let limit = limit.unwrap_or(10);
|
|
104
|
+
let offset = offset.unwrap_or(0);
|
|
105
|
+
|
|
106
|
+
perform_search(&query, limit, offset).await
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Frontend**:
|
|
111
|
+
```typescript
|
|
112
|
+
// All optional params
|
|
113
|
+
await invoke('search_users', { query: 'john' });
|
|
114
|
+
|
|
115
|
+
// Some optional params
|
|
116
|
+
await invoke('search_users', {
|
|
117
|
+
query: 'john',
|
|
118
|
+
limit: 20
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// All params
|
|
122
|
+
await invoke('search_users', {
|
|
123
|
+
query: 'john',
|
|
124
|
+
limit: 20,
|
|
125
|
+
offset: 10
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Special Injected Parameters
|
|
130
|
+
|
|
131
|
+
### State Injection
|
|
132
|
+
|
|
133
|
+
```rust
|
|
134
|
+
use tauri::State;
|
|
135
|
+
|
|
136
|
+
#[tauri::command]
|
|
137
|
+
async fn get_user_count(
|
|
138
|
+
state: State<'_, AppState>
|
|
139
|
+
) -> Result<usize, String> {
|
|
140
|
+
let db = state.database.lock().await;
|
|
141
|
+
Ok(db.count_users())
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Multiple state parameters
|
|
145
|
+
#[tauri::command]
|
|
146
|
+
async fn complex_operation(
|
|
147
|
+
input: String,
|
|
148
|
+
state: State<'_, AppState>,
|
|
149
|
+
) -> Result<String, String> {
|
|
150
|
+
// State is NOT passed from frontend
|
|
151
|
+
let config = state.config.lock().await;
|
|
152
|
+
process_with_config(&input, &config).await
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Window Parameter
|
|
157
|
+
|
|
158
|
+
```rust
|
|
159
|
+
use tauri::Window;
|
|
160
|
+
|
|
161
|
+
#[tauri::command]
|
|
162
|
+
async fn long_task(
|
|
163
|
+
window: Window,
|
|
164
|
+
) -> Result<(), String> {
|
|
165
|
+
for i in 0..100 {
|
|
166
|
+
// Emit progress to THIS window
|
|
167
|
+
window.emit("progress", i)
|
|
168
|
+
.map_err(|e| e.to_string())?;
|
|
169
|
+
|
|
170
|
+
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
171
|
+
}
|
|
172
|
+
Ok(())
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Get window properties
|
|
176
|
+
#[tauri::command]
|
|
177
|
+
async fn get_window_info(
|
|
178
|
+
window: Window,
|
|
179
|
+
) -> Result<WindowInfo, String> {
|
|
180
|
+
Ok(WindowInfo {
|
|
181
|
+
label: window.label().to_string(),
|
|
182
|
+
title: window.title().map_err(|e| e.to_string())?,
|
|
183
|
+
is_visible: window.is_visible().map_err(|e| e.to_string())?,
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### AppHandle Parameter
|
|
189
|
+
|
|
190
|
+
```rust
|
|
191
|
+
use tauri::{AppHandle, Manager};
|
|
192
|
+
|
|
193
|
+
#[tauri::command]
|
|
194
|
+
async fn create_new_window(
|
|
195
|
+
name: String,
|
|
196
|
+
app: AppHandle,
|
|
197
|
+
) -> Result<(), String> {
|
|
198
|
+
use tauri::{WindowBuilder, WindowUrl};
|
|
199
|
+
|
|
200
|
+
WindowBuilder::new(
|
|
201
|
+
&app,
|
|
202
|
+
name,
|
|
203
|
+
WindowUrl::App("index.html".into())
|
|
204
|
+
)
|
|
205
|
+
.title("New Window")
|
|
206
|
+
.build()
|
|
207
|
+
.map_err(|e| e.to_string())?;
|
|
208
|
+
|
|
209
|
+
Ok(())
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Access all windows
|
|
213
|
+
#[tauri::command]
|
|
214
|
+
async fn broadcast_message(
|
|
215
|
+
message: String,
|
|
216
|
+
app: AppHandle,
|
|
217
|
+
) -> Result<(), String> {
|
|
218
|
+
app.emit_all("broadcast", message)
|
|
219
|
+
.map_err(|e| e.to_string())
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Combining Special and Regular Parameters
|
|
224
|
+
|
|
225
|
+
```rust
|
|
226
|
+
#[tauri::command]
|
|
227
|
+
async fn save_document(
|
|
228
|
+
// Regular parameters (from frontend)
|
|
229
|
+
filename: String,
|
|
230
|
+
content: String,
|
|
231
|
+
// Special parameters (injected by Tauri)
|
|
232
|
+
state: State<'_, AppState>,
|
|
233
|
+
window: Window,
|
|
234
|
+
app: AppHandle,
|
|
235
|
+
) -> Result<(), String> {
|
|
236
|
+
// Validate
|
|
237
|
+
if filename.is_empty() {
|
|
238
|
+
return Err("Filename required".to_string());
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Get safe path
|
|
242
|
+
let app_data = app.path_resolver()
|
|
243
|
+
.app_data_dir()
|
|
244
|
+
.ok_or("Failed to get app data dir")?;
|
|
245
|
+
|
|
246
|
+
let file_path = app_data.join(&filename);
|
|
247
|
+
|
|
248
|
+
// Save
|
|
249
|
+
tokio::fs::write(&file_path, content)
|
|
250
|
+
.await
|
|
251
|
+
.map_err(|e| e.to_string())?;
|
|
252
|
+
|
|
253
|
+
// Update state
|
|
254
|
+
{
|
|
255
|
+
let mut docs = state.documents.lock().await;
|
|
256
|
+
docs.insert(filename.clone(), file_path);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Notify window
|
|
260
|
+
window.emit("document-saved", filename)
|
|
261
|
+
.map_err(|e| e.to_string())?;
|
|
262
|
+
|
|
263
|
+
Ok(())
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Frontend** (only passes regular parameters):
|
|
268
|
+
```typescript
|
|
269
|
+
await invoke('save_document', {
|
|
270
|
+
filename: 'notes.txt',
|
|
271
|
+
content: 'My content'
|
|
272
|
+
// State, Window, AppHandle NOT passed - Tauri injects them
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Command Organization
|
|
277
|
+
|
|
278
|
+
### Modular Command Structure
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
src-tauri/src/
|
|
282
|
+
├── main.rs
|
|
283
|
+
├── commands/
|
|
284
|
+
│ ├── mod.rs
|
|
285
|
+
│ ├── files.rs
|
|
286
|
+
│ ├── database.rs
|
|
287
|
+
│ └── system.rs
|
|
288
|
+
└── state.rs
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**commands/mod.rs**:
|
|
292
|
+
```rust
|
|
293
|
+
pub mod files;
|
|
294
|
+
pub mod database;
|
|
295
|
+
pub mod system;
|
|
296
|
+
|
|
297
|
+
// Re-export all commands
|
|
298
|
+
pub use files::*;
|
|
299
|
+
pub use database::*;
|
|
300
|
+
pub use system::*;
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**commands/files.rs**:
|
|
304
|
+
```rust
|
|
305
|
+
use tauri::{AppHandle, State};
|
|
306
|
+
use crate::state::AppState;
|
|
307
|
+
|
|
308
|
+
#[tauri::command]
|
|
309
|
+
pub async fn read_file(
|
|
310
|
+
path: String,
|
|
311
|
+
app: AppHandle,
|
|
312
|
+
) -> Result<String, String> {
|
|
313
|
+
// Implementation
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
#[tauri::command]
|
|
317
|
+
pub async fn write_file(
|
|
318
|
+
path: String,
|
|
319
|
+
content: String,
|
|
320
|
+
app: AppHandle,
|
|
321
|
+
) -> Result<(), String> {
|
|
322
|
+
// Implementation
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
#[tauri::command]
|
|
326
|
+
pub async fn list_files(
|
|
327
|
+
directory: String,
|
|
328
|
+
state: State<'_, AppState>,
|
|
329
|
+
) -> Result<Vec<String>, String> {
|
|
330
|
+
// Implementation
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**main.rs** registration:
|
|
335
|
+
```rust
|
|
336
|
+
mod commands;
|
|
337
|
+
mod state;
|
|
338
|
+
|
|
339
|
+
use commands::*;
|
|
340
|
+
|
|
341
|
+
fn main() {
|
|
342
|
+
tauri::Builder::default()
|
|
343
|
+
.manage(state::AppState::new())
|
|
344
|
+
.invoke_handler(tauri::generate_handler![
|
|
345
|
+
// File commands
|
|
346
|
+
read_file,
|
|
347
|
+
write_file,
|
|
348
|
+
list_files,
|
|
349
|
+
// Database commands
|
|
350
|
+
query_database,
|
|
351
|
+
insert_record,
|
|
352
|
+
// System commands
|
|
353
|
+
get_system_info,
|
|
354
|
+
check_permissions,
|
|
355
|
+
])
|
|
356
|
+
.run(tauri::generate_context!())
|
|
357
|
+
.expect("error while running tauri application");
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Grouped Command Namespaces
|
|
362
|
+
|
|
363
|
+
```rust
|
|
364
|
+
// Group related commands with prefixes
|
|
365
|
+
#[tauri::command]
|
|
366
|
+
async fn file_read(path: String) -> Result<String, String> { }
|
|
367
|
+
|
|
368
|
+
#[tauri::command]
|
|
369
|
+
async fn file_write(path: String, content: String) -> Result<(), String> { }
|
|
370
|
+
|
|
371
|
+
#[tauri::command]
|
|
372
|
+
async fn file_delete(path: String) -> Result<(), String> { }
|
|
373
|
+
|
|
374
|
+
#[tauri::command]
|
|
375
|
+
async fn db_query(sql: String) -> Result<Vec<Row>, String> { }
|
|
376
|
+
|
|
377
|
+
#[tauri::command]
|
|
378
|
+
async fn db_insert(table: String, data: HashMap<String, String>) -> Result<(), String> { }
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Frontend service wrappers**:
|
|
382
|
+
```typescript
|
|
383
|
+
// src/services/fileService.ts
|
|
384
|
+
export const fileService = {
|
|
385
|
+
read: (path: string) => invoke<string>('file_read', { path }),
|
|
386
|
+
write: (path: string, content: string) => invoke('file_write', { path, content }),
|
|
387
|
+
delete: (path: string) => invoke('file_delete', { path }),
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
// src/services/dbService.ts
|
|
391
|
+
export const dbService = {
|
|
392
|
+
query: (sql: string) => invoke<Row[]>('db_query', { sql }),
|
|
393
|
+
insert: (table: string, data: Record<string, string>) =>
|
|
394
|
+
invoke('db_insert', { table, data }),
|
|
395
|
+
};
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## Advanced Parameter Patterns
|
|
399
|
+
|
|
400
|
+
### Generic Return Types
|
|
401
|
+
|
|
402
|
+
```rust
|
|
403
|
+
use serde::Serialize;
|
|
404
|
+
|
|
405
|
+
#[derive(Serialize)]
|
|
406
|
+
struct ApiResponse<T> {
|
|
407
|
+
success: bool,
|
|
408
|
+
data: Option<T>,
|
|
409
|
+
error: Option<String>,
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
#[tauri::command]
|
|
413
|
+
async fn fetch_user(id: u64) -> Result<ApiResponse<User>, String> {
|
|
414
|
+
match get_user(id).await {
|
|
415
|
+
Ok(user) => Ok(ApiResponse {
|
|
416
|
+
success: true,
|
|
417
|
+
data: Some(user),
|
|
418
|
+
error: None,
|
|
419
|
+
}),
|
|
420
|
+
Err(e) => Ok(ApiResponse {
|
|
421
|
+
success: false,
|
|
422
|
+
data: None,
|
|
423
|
+
error: Some(e.to_string()),
|
|
424
|
+
}),
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Enum Parameters
|
|
430
|
+
|
|
431
|
+
```rust
|
|
432
|
+
use serde::Deserialize;
|
|
433
|
+
|
|
434
|
+
#[derive(Deserialize)]
|
|
435
|
+
#[serde(rename_all = "lowercase")]
|
|
436
|
+
enum SortOrder {
|
|
437
|
+
Asc,
|
|
438
|
+
Desc,
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
#[derive(Deserialize)]
|
|
442
|
+
struct QueryOptions {
|
|
443
|
+
limit: usize,
|
|
444
|
+
offset: usize,
|
|
445
|
+
sort: SortOrder,
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
#[tauri::command]
|
|
449
|
+
async fn query_items(
|
|
450
|
+
query: String,
|
|
451
|
+
options: QueryOptions,
|
|
452
|
+
) -> Result<Vec<Item>, String> {
|
|
453
|
+
let results = search(&query).await?;
|
|
454
|
+
|
|
455
|
+
let sorted = match options.sort {
|
|
456
|
+
SortOrder::Asc => results.sort_by_key(|i| i.date),
|
|
457
|
+
SortOrder::Desc => results.sort_by_key(|i| std::cmp::Reverse(i.date)),
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
Ok(sorted.into_iter()
|
|
461
|
+
.skip(options.offset)
|
|
462
|
+
.take(options.limit)
|
|
463
|
+
.collect())
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
**Frontend**:
|
|
468
|
+
```typescript
|
|
469
|
+
const results = await invoke<Item[]>('query_items', {
|
|
470
|
+
query: 'search term',
|
|
471
|
+
options: {
|
|
472
|
+
limit: 20,
|
|
473
|
+
offset: 0,
|
|
474
|
+
sort: 'asc' // or 'desc'
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Best Practices
|
|
480
|
+
|
|
481
|
+
1. **Use structs for complex data** - Better type safety and validation
|
|
482
|
+
2. **Validate early** - Check parameters before expensive operations
|
|
483
|
+
3. **Group related commands** - Use prefixes or modules
|
|
484
|
+
4. **Document parameters** - Use doc comments for clarity
|
|
485
|
+
5. **Handle optionals explicitly** - Use `unwrap_or` or `ok_or`
|
|
486
|
+
6. **Type special parameters last** - Convention: regular params, then State, Window, AppHandle
|
|
487
|
+
7. **Use meaningful error messages** - Help frontend developers debug
|
|
488
|
+
|
|
489
|
+
## Common Pitfalls
|
|
490
|
+
|
|
491
|
+
❌ **Passing special parameters from frontend**:
|
|
492
|
+
```typescript
|
|
493
|
+
// WRONG - State/Window/AppHandle are injected, not passed
|
|
494
|
+
await invoke('my_command', { state: someState }); // Error!
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
❌ **Forgetting serde::Deserialize**:
|
|
498
|
+
```rust
|
|
499
|
+
// WRONG - struct won't deserialize
|
|
500
|
+
struct MyInput {
|
|
501
|
+
name: String,
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// CORRECT
|
|
505
|
+
#[derive(serde::Deserialize)]
|
|
506
|
+
struct MyInput {
|
|
507
|
+
name: String,
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
❌ **Incorrect parameter order**:
|
|
512
|
+
```rust
|
|
513
|
+
// WRONG - special parameters should come after regular ones
|
|
514
|
+
#[tauri::command]
|
|
515
|
+
async fn bad(
|
|
516
|
+
state: State<'_, AppState>,
|
|
517
|
+
input: String, // Regular param after special
|
|
518
|
+
) -> Result<(), String> { }
|
|
519
|
+
|
|
520
|
+
// CORRECT
|
|
521
|
+
#[tauri::command]
|
|
522
|
+
async fn good(
|
|
523
|
+
input: String, // Regular params first
|
|
524
|
+
state: State<'_, AppState>, // Special params last
|
|
525
|
+
) -> Result<(), String> { }
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
## Summary
|
|
529
|
+
|
|
530
|
+
- **Structs** enable complex, validated parameters
|
|
531
|
+
- **Special parameters** (State/Window/AppHandle) are injected by Tauri
|
|
532
|
+
- **Optional parameters** use `Option<T>` with defaults
|
|
533
|
+
- **Organize commands** in modules for maintainability
|
|
534
|
+
- **Always validate** parameters before processing
|
|
535
|
+
- **Regular parameters come first**, special parameters last
|