claude-mpm 5.4.59__py3-none-any.whl → 5.4.62__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.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (128) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +5 -0
  3. claude_mpm/scripts/start_activity_logging.py +0 -0
  4. claude_mpm/services/agents/deployment/agent_template_builder.py +8 -0
  5. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  6. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  7. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  8. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  9. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  10. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  11. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  12. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  13. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  14. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  15. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  16. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  17. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  18. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  19. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  20. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  21. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  22. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  23. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  24. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  25. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  26. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  27. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  28. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  29. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  30. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  31. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  32. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  33. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  34. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  35. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  36. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  37. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  38. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  39. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  40. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  41. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  42. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  43. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  44. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  45. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  46. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  47. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  48. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  49. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  50. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  51. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  52. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  53. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  54. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  55. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  56. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  57. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  58. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  59. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  60. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  61. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  62. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  63. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  64. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  65. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  66. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  67. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  68. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  69. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  70. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  71. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  72. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  73. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  74. claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
  75. claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
  76. claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
  77. claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
  78. claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
  79. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  80. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  81. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  82. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  83. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  84. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  85. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  86. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  87. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  88. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  89. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  90. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  91. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  92. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  93. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  94. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  95. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  96. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  97. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  98. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  99. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  100. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  101. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  102. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  103. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  104. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  105. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  106. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  107. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  108. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  109. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  110. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  111. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  112. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  113. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  114. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  115. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  116. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  117. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  118. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  119. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  120. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  121. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  122. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.62.dist-info}/METADATA +1 -1
  123. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.62.dist-info}/RECORD +127 -10
  124. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.62.dist-info}/WHEEL +0 -0
  125. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.62.dist-info}/entry_points.txt +0 -0
  126. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.62.dist-info}/licenses/LICENSE +0 -0
  127. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.62.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  128. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.62.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,648 @@
1
+ ---
2
+ name: tauri-event-system
3
+ description: Advanced Tauri event patterns for bidirectional communication, streaming data, window-to-window messaging, and custom event handling
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 event patterns: bidirectional events, streaming, window messaging, custom payloads, listener management"
11
+ when_to_use: "When implementing real-time updates, progress tracking, inter-window communication, or streaming data"
12
+ quick_start: "1. Backend emits with window.emit() 2. Frontend listens with listen() 3. Clean up with unlisten() 4. Use typed payloads"
13
+ context_limit: 500
14
+ tags:
15
+ - tauri
16
+ - events
17
+ - ipc
18
+ - streaming
19
+ - real-time
20
+ requires_tools: []
21
+ ---
22
+
23
+ # Tauri Advanced Event System
24
+
25
+ ## Event Fundamentals
26
+
27
+ ### Backend → Frontend Events
28
+
29
+ **Basic event emission**:
30
+ ```rust
31
+ use tauri::Window;
32
+
33
+ #[tauri::command]
34
+ async fn start_download(
35
+ url: String,
36
+ window: Window,
37
+ ) -> Result<(), String> {
38
+ window.emit("download-started", url)
39
+ .map_err(|e| e.to_string())?;
40
+
41
+ // Perform download...
42
+
43
+ window.emit("download-complete", "Success")
44
+ .map_err(|e| e.to_string())
45
+ }
46
+ ```
47
+
48
+ **Frontend listener**:
49
+ ```typescript
50
+ import { listen, UnlistenFn } from '@tauri-apps/api/event';
51
+
52
+ const unlisten = await listen<string>('download-started', (event) => {
53
+ console.log('Download started:', event.payload);
54
+ });
55
+
56
+ // Clean up when done
57
+ unlisten();
58
+ ```
59
+
60
+ ## Structured Event Payloads
61
+
62
+ ### Typed Events with Serde
63
+
64
+ **Backend**:
65
+ ```rust
66
+ use serde::Serialize;
67
+
68
+ #[derive(Serialize, Clone)]
69
+ struct ProgressEvent {
70
+ current: usize,
71
+ total: usize,
72
+ percentage: f64,
73
+ message: String,
74
+ speed_mbps: Option<f64>,
75
+ }
76
+
77
+ #[tauri::command]
78
+ async fn download_file(
79
+ url: String,
80
+ window: Window,
81
+ ) -> Result<(), String> {
82
+ let total_size = get_file_size(&url).await?;
83
+
84
+ for chunk in 0..total_size {
85
+ // Download chunk...
86
+
87
+ let progress = ProgressEvent {
88
+ current: chunk,
89
+ total: total_size,
90
+ percentage: (chunk as f64 / total_size as f64) * 100.0,
91
+ message: format!("Downloading... {}/{}", chunk, total_size),
92
+ speed_mbps: Some(calculate_speed()),
93
+ };
94
+
95
+ window.emit("download-progress", progress)
96
+ .map_err(|e| e.to_string())?;
97
+ }
98
+
99
+ Ok(())
100
+ }
101
+ ```
102
+
103
+ **Frontend**:
104
+ ```typescript
105
+ interface ProgressEvent {
106
+ current: number;
107
+ total: number;
108
+ percentage: number;
109
+ message: string;
110
+ speed_mbps?: number;
111
+ }
112
+
113
+ const unlisten = await listen<ProgressEvent>('download-progress', (event) => {
114
+ const { current, total, percentage, message, speed_mbps } = event.payload;
115
+
116
+ updateProgressBar(percentage);
117
+ updateStatus(message);
118
+
119
+ if (speed_mbps) {
120
+ updateSpeed(speed_mbps);
121
+ }
122
+ });
123
+ ```
124
+
125
+ ### Complex Event Payloads
126
+
127
+ ```rust
128
+ #[derive(Serialize, Clone)]
129
+ #[serde(tag = "type", content = "data")]
130
+ enum AppEvent {
131
+ UserLoggedIn { user_id: String, username: String },
132
+ UserLoggedOut { user_id: String },
133
+ DataSynced { items_count: usize, timestamp: String },
134
+ ErrorOccurred { code: String, message: String, recoverable: bool },
135
+ }
136
+
137
+ #[tauri::command]
138
+ async fn perform_login(
139
+ username: String,
140
+ password: String,
141
+ window: Window,
142
+ ) -> Result<String, String> {
143
+ let user = authenticate(&username, &password).await?;
144
+
145
+ // Emit structured event
146
+ window.emit("app-event", AppEvent::UserLoggedIn {
147
+ user_id: user.id.clone(),
148
+ username: user.username.clone(),
149
+ }).map_err(|e| e.to_string())?;
150
+
151
+ Ok(user.id)
152
+ }
153
+ ```
154
+
155
+ **Frontend**:
156
+ ```typescript
157
+ type AppEvent =
158
+ | { type: 'UserLoggedIn'; data: { user_id: string; username: string } }
159
+ | { type: 'UserLoggedOut'; data: { user_id: string } }
160
+ | { type: 'DataSynced'; data: { items_count: number; timestamp: string } }
161
+ | { type: 'ErrorOccurred'; data: { code: string; message: string; recoverable: boolean } };
162
+
163
+ listen<AppEvent>('app-event', (event) => {
164
+ const appEvent = event.payload;
165
+
166
+ switch (appEvent.type) {
167
+ case 'UserLoggedIn':
168
+ handleLogin(appEvent.data.user_id, appEvent.data.username);
169
+ break;
170
+ case 'UserLoggedOut':
171
+ handleLogout(appEvent.data.user_id);
172
+ break;
173
+ case 'DataSynced':
174
+ showSyncSuccess(appEvent.data.items_count);
175
+ break;
176
+ case 'ErrorOccurred':
177
+ handleError(appEvent.data);
178
+ break;
179
+ }
180
+ });
181
+ ```
182
+
183
+ ## Streaming Data Patterns
184
+
185
+ ### Real-Time Data Stream
186
+
187
+ ```rust
188
+ #[tauri::command]
189
+ async fn stream_sensor_data(
190
+ sensor_id: String,
191
+ window: Window,
192
+ ) -> Result<(), String> {
193
+ let mut interval = tokio::time::interval(Duration::from_millis(100));
194
+
195
+ for _ in 0..100 {
196
+ interval.tick().await;
197
+
198
+ let reading = read_sensor(&sensor_id).await?;
199
+
200
+ window.emit("sensor-reading", reading)
201
+ .map_err(|e| e.to_string())?;
202
+ }
203
+
204
+ window.emit("sensor-stream-ended", sensor_id)
205
+ .map_err(|e| e.to_string())
206
+ }
207
+ ```
208
+
209
+ **Frontend with React**:
210
+ ```typescript
211
+ import { useEffect, useState } from 'react';
212
+ import { listen } from '@tauri-apps/api/event';
213
+
214
+ interface SensorReading {
215
+ value: number;
216
+ timestamp: number;
217
+ unit: string;
218
+ }
219
+
220
+ function SensorMonitor() {
221
+ const [readings, setReadings] = useState<SensorReading[]>([]);
222
+
223
+ useEffect(() => {
224
+ let unlisten: UnlistenFn | undefined;
225
+
226
+ listen<SensorReading>('sensor-reading', (event) => {
227
+ setReadings(prev => [...prev.slice(-99), event.payload]);
228
+ }).then(fn => unlisten = fn);
229
+
230
+ return () => unlisten?.();
231
+ }, []);
232
+
233
+ return (
234
+ <div>
235
+ {readings.map((r, i) => (
236
+ <div key={i}>{r.value} {r.unit}</div>
237
+ ))}
238
+ </div>
239
+ );
240
+ }
241
+ ```
242
+
243
+ ### Buffered Streaming
244
+
245
+ ```rust
246
+ #[tauri::command]
247
+ async fn stream_logs(
248
+ log_file: String,
249
+ window: Window,
250
+ ) -> Result<(), String> {
251
+ use tokio::io::{AsyncBufReadExt, BufReader};
252
+ use tokio::fs::File;
253
+
254
+ let file = File::open(log_file).await
255
+ .map_err(|e| e.to_string())?;
256
+
257
+ let reader = BufReader::new(file);
258
+ let mut lines = reader.lines();
259
+
260
+ let mut buffer = Vec::new();
261
+
262
+ while let Some(line) = lines.next_line().await
263
+ .map_err(|e| e.to_string())? {
264
+
265
+ buffer.push(line);
266
+
267
+ // Send in batches of 10 lines
268
+ if buffer.len() >= 10 {
269
+ window.emit("log-batch", buffer.clone())
270
+ .map_err(|e| e.to_string())?;
271
+ buffer.clear();
272
+ }
273
+ }
274
+
275
+ // Send remaining lines
276
+ if !buffer.is_empty() {
277
+ window.emit("log-batch", buffer)
278
+ .map_err(|e| e.to_string())?;
279
+ }
280
+
281
+ Ok(())
282
+ }
283
+ ```
284
+
285
+ ## Multi-Window Communication
286
+
287
+ ### Broadcasting to All Windows
288
+
289
+ ```rust
290
+ use tauri::{AppHandle, Manager};
291
+
292
+ #[tauri::command]
293
+ async fn broadcast_message(
294
+ message: String,
295
+ app: AppHandle,
296
+ ) -> Result<(), String> {
297
+ // Emit to ALL windows
298
+ app.emit_all("broadcast", message)
299
+ .map_err(|e| e.to_string())
300
+ }
301
+ ```
302
+
303
+ ### Targeted Window Messaging
304
+
305
+ ```rust
306
+ #[tauri::command]
307
+ async fn send_to_window(
308
+ target_window: String,
309
+ message: String,
310
+ app: AppHandle,
311
+ ) -> Result<(), String> {
312
+ // Get specific window
313
+ if let Some(window) = app.get_window(&target_window) {
314
+ window.emit("private-message", message)
315
+ .map_err(|e| e.to_string())?;
316
+ Ok(())
317
+ } else {
318
+ Err(format!("Window '{}' not found", target_window))
319
+ }
320
+ }
321
+ ```
322
+
323
+ ### Window-to-Window via Backend
324
+
325
+ **Window A (sender)**:
326
+ ```typescript
327
+ import { invoke } from '@tauri-apps/api/core';
328
+
329
+ async function sendToSettings(data: any) {
330
+ await invoke('relay_to_settings', { data });
331
+ }
332
+ ```
333
+
334
+ **Backend relay**:
335
+ ```rust
336
+ #[tauri::command]
337
+ async fn relay_to_settings(
338
+ data: serde_json::Value,
339
+ app: AppHandle,
340
+ ) -> Result<(), String> {
341
+ if let Some(settings_window) = app.get_window("settings") {
342
+ settings_window.emit("data-update", data)
343
+ .map_err(|e| e.to_string())?;
344
+ }
345
+ Ok(())
346
+ }
347
+ ```
348
+
349
+ **Window B (receiver - settings)**:
350
+ ```typescript
351
+ import { listen } from '@tauri-apps/api/event';
352
+
353
+ useEffect(() => {
354
+ let unlisten: UnlistenFn | undefined;
355
+
356
+ listen('data-update', (event) => {
357
+ console.log('Received from main window:', event.payload);
358
+ updateSettings(event.payload);
359
+ }).then(fn => unlisten = fn);
360
+
361
+ return () => unlisten?.();
362
+ }, []);
363
+ ```
364
+
365
+ ## Frontend → Backend Events
366
+
367
+ ### Custom Frontend Events
368
+
369
+ ```typescript
370
+ import { emit } from '@tauri-apps/api/event';
371
+
372
+ // Frontend emits event
373
+ await emit('user-action', {
374
+ action: 'button-click',
375
+ button_id: 'save-button',
376
+ timestamp: Date.now()
377
+ });
378
+ ```
379
+
380
+ **Backend listener**:
381
+ ```rust
382
+ use tauri::{Manager, Listener};
383
+
384
+ fn main() {
385
+ tauri::Builder::default()
386
+ .setup(|app| {
387
+ let app_handle = app.handle();
388
+
389
+ // Listen for frontend events
390
+ app_handle.listen_global("user-action", move |event| {
391
+ if let Some(payload) = event.payload() {
392
+ println!("User action: {}", payload);
393
+ // Process event...
394
+ }
395
+ });
396
+
397
+ Ok(())
398
+ })
399
+ .run(tauri::generate_context!())
400
+ .expect("error while running tauri application");
401
+ }
402
+ ```
403
+
404
+ ## Advanced Listener Management
405
+
406
+ ### React Hook for Events
407
+
408
+ ```typescript
409
+ import { useEffect, useState } from 'react';
410
+ import { listen, UnlistenFn } from '@tauri-apps/api/event';
411
+
412
+ function useEvent<T>(eventName: string): T | null {
413
+ const [payload, setPayload] = useState<T | null>(null);
414
+
415
+ useEffect(() => {
416
+ let unlisten: UnlistenFn | undefined;
417
+
418
+ listen<T>(eventName, (event) => {
419
+ setPayload(event.payload);
420
+ }).then(fn => unlisten = fn);
421
+
422
+ return () => unlisten?.();
423
+ }, [eventName]);
424
+
425
+ return payload;
426
+ }
427
+
428
+ // Usage
429
+ function ProgressDisplay() {
430
+ const progress = useEvent<ProgressEvent>('download-progress');
431
+
432
+ if (!progress) return null;
433
+
434
+ return (
435
+ <div>
436
+ Progress: {progress.percentage.toFixed(2)}%
437
+ </div>
438
+ );
439
+ }
440
+ ```
441
+
442
+ ### Event Queue Pattern
443
+
444
+ ```typescript
445
+ import { listen } from '@tauri-apps/api/event';
446
+
447
+ class EventQueue<T> {
448
+ private queue: T[] = [];
449
+ private unlisten?: UnlistenFn;
450
+
451
+ async start(eventName: string) {
452
+ this.unlisten = await listen<T>(eventName, (event) => {
453
+ this.queue.push(event.payload);
454
+ });
455
+ }
456
+
457
+ dequeue(): T | undefined {
458
+ return this.queue.shift();
459
+ }
460
+
461
+ clear() {
462
+ this.queue = [];
463
+ }
464
+
465
+ stop() {
466
+ this.unlisten?.();
467
+ }
468
+
469
+ get length() {
470
+ return this.queue.length;
471
+ }
472
+ }
473
+
474
+ // Usage
475
+ const progressQueue = new EventQueue<ProgressEvent>();
476
+ await progressQueue.start('download-progress');
477
+
478
+ // Process queue periodically
479
+ setInterval(() => {
480
+ while (progressQueue.length > 0) {
481
+ const event = progressQueue.dequeue();
482
+ processProgress(event);
483
+ }
484
+ }, 100);
485
+ ```
486
+
487
+ ### One-Time Events
488
+
489
+ ```typescript
490
+ import { once } from '@tauri-apps/api/event';
491
+
492
+ // Listen for event only once
493
+ await once<string>('initialization-complete', (event) => {
494
+ console.log('App initialized:', event.payload);
495
+ startApp();
496
+ });
497
+ ```
498
+
499
+ ## Error Handling in Events
500
+
501
+ ### Safe Event Emission
502
+
503
+ ```rust
504
+ async fn emit_safe(window: &Window, event: &str, payload: impl Serialize) -> Result<(), String> {
505
+ window.emit(event, payload)
506
+ .map_err(|e| {
507
+ eprintln!("Failed to emit event '{}': {}", event, e);
508
+ e.to_string()
509
+ })
510
+ }
511
+
512
+ #[tauri::command]
513
+ async fn process_with_events(
514
+ window: Window,
515
+ ) -> Result<(), String> {
516
+ emit_safe(&window, "processing-started", "Starting...")
517
+ .await?;
518
+
519
+ // Process...
520
+
521
+ emit_safe(&window, "processing-complete", "Done!")
522
+ .await?;
523
+
524
+ Ok(())
525
+ }
526
+ ```
527
+
528
+ ## Performance Considerations
529
+
530
+ ### Throttling Events
531
+
532
+ ```rust
533
+ use std::time::{Duration, Instant};
534
+
535
+ #[tauri::command]
536
+ async fn high_frequency_updates(
537
+ window: Window,
538
+ ) -> Result<(), String> {
539
+ let mut last_emit = Instant::now();
540
+ let throttle_duration = Duration::from_millis(100);
541
+
542
+ for i in 0..10000 {
543
+ let value = compute_value(i);
544
+
545
+ // Only emit every 100ms
546
+ if last_emit.elapsed() >= throttle_duration {
547
+ window.emit("update", value)
548
+ .map_err(|e| e.to_string())?;
549
+ last_emit = Instant::now();
550
+ }
551
+ }
552
+
553
+ Ok(())
554
+ }
555
+ ```
556
+
557
+ ### Batching Events
558
+
559
+ ```rust
560
+ #[tauri::command]
561
+ async fn batch_updates(
562
+ window: Window,
563
+ ) -> Result<(), String> {
564
+ let mut batch = Vec::new();
565
+
566
+ for item in process_items() {
567
+ batch.push(item);
568
+
569
+ // Emit in batches of 50
570
+ if batch.len() >= 50 {
571
+ window.emit("batch-update", batch.clone())
572
+ .map_err(|e| e.to_string())?;
573
+ batch.clear();
574
+ }
575
+ }
576
+
577
+ // Emit remaining items
578
+ if !batch.is_empty() {
579
+ window.emit("batch-update", batch)
580
+ .map_err(|e| e.to_string())?;
581
+ }
582
+
583
+ Ok(())
584
+ }
585
+ ```
586
+
587
+ ## Best Practices
588
+
589
+ 1. **Always clean up listeners** - Use `unlisten()` to prevent memory leaks
590
+ 2. **Type event payloads** - Define interfaces for type safety
591
+ 3. **Use structured events** - Tagged unions for multiple event types
592
+ 4. **Throttle high-frequency events** - Prevent overwhelming frontend
593
+ 5. **Batch when possible** - Reduce serialization overhead
594
+ 6. **Handle errors gracefully** - Log failed emissions, don't crash
595
+ 7. **Use once() for one-time events** - Initialization, completion signals
596
+ 8. **Namespace event names** - Use prefixes like "download:", "user:", "system:"
597
+
598
+ ## Common Pitfalls
599
+
600
+ ❌ **Forgetting to unlisten**:
601
+ ```typescript
602
+ // WRONG - memory leak
603
+ function Component() {
604
+ listen('my-event', handler); // Never cleaned up!
605
+ }
606
+
607
+ // CORRECT
608
+ function Component() {
609
+ useEffect(() => {
610
+ let unlisten: UnlistenFn | undefined;
611
+ listen('my-event', handler).then(fn => unlisten = fn);
612
+ return () => unlisten?.();
613
+ }, []);
614
+ }
615
+ ```
616
+
617
+ ❌ **Not handling serialization errors**:
618
+ ```rust
619
+ // WRONG - struct can't serialize
620
+ #[derive(Clone)] // Missing Serialize!
621
+ struct Event { }
622
+
623
+ window.emit("event", Event {}); // Runtime error!
624
+
625
+ // CORRECT
626
+ #[derive(Serialize, Clone)]
627
+ struct Event { }
628
+ ```
629
+
630
+ ❌ **Emitting too frequently**:
631
+ ```rust
632
+ // WRONG - 10000 events in quick succession
633
+ for i in 0..10000 {
634
+ window.emit("update", i); // Overwhelming!
635
+ }
636
+
637
+ // CORRECT - throttle or batch
638
+ ```
639
+
640
+ ## Summary
641
+
642
+ - **Events are async** - Backend → Frontend communication
643
+ - **Always type payloads** - Use serde::Serialize + TypeScript interfaces
644
+ - **Clean up listeners** - Call `unlisten()` in cleanup
645
+ - **Throttle/batch** - High-frequency events need rate limiting
646
+ - **Use structured payloads** - Tagged unions for multiple event types
647
+ - **Window targeting** - `emit()` for specific, `emit_all()` for broadcast
648
+ - **Frontend events** - Use `emit()` from frontend, listen in backend setup