Alle PlaybooksNative Utility

Einen nativen Befehl hinzufügen

Eine schnelle Rust-Operation über app-api, einen Tauri-Befehl mit eigener Berechtigung und den Native Client für die UI bereitstellen, mit generierten Typen und Tests auf beiden Seiten.

Wann du es brauchst

Die UI braucht eine sofortige Antwort vom Rust-Kern, zum Beispiel die Größe der lokalen Datenbank oder Details zu einer gewählten Datei. Die Schritte verwenden einen Befehl storage_info als Beispiel. Arbeit, die länger als einen Moment dauern kann (einen Ordnerbaum lesen, Netzwerk, Geräte), ist ein Job: siehe das Playbook "Einen Job-Handler hinzufügen".

Regeln

  • Der Weg ist immer UI → packages/native-client → Tauri-Befehl → crates/app-api → Core-Crates. Der Befehl ruft nur eine Methode von AppApi auf; keine Logik in apps/desktop/src-tauri.
  • Jeder Befehl braucht eine eigene Berechtigung in apps/desktop/src-tauri/capabilities/main-window.json. Keine globalen oder Wildcard-Berechtigungen.
  • Typen überqueren die Grenze als DTOs aus crates/app-api/src/dto.rs; die TypeScript-Versionen werden generiert, nie von Hand geschrieben.
  • Fehler sind ApiError-Werte mit einem stabilen RW_*-Code, nie Sätze. Die UI übersetzt den Code.
  • Ein Pfad aus der UI läuft durch validate_path, bevor er verwendet wird.

Schritte

  1. Ergänze das DTO in crates/app-api/src/dto.rs mit denselben Derives und Attributen wie die anderen (Serialize, Deserialize, das cfg_attr für ts-export und rename_all = "camelCase"). Markiere u64-Felder wie in JobDto mit ts(type = "number"):

    #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
    #[cfg_attr(feature = "ts-export", derive(TS), ts(export))]
    #[serde(rename_all = "camelCase")]
    pub struct StorageInfoDto {
        pub data_dir: String,
        #[cfg_attr(feature = "ts-export", ts(type = "number"))]
        pub database_bytes: u64,
    }
    
  2. Ergänze die Methode in AppApi in crates/app-api/src/api.rs, mit Rückgabe Result<StorageInfoDto, ApiError>. Baue Fehler mit ApiError::new("RW_...", category, recoverable) und prüfe deaktivierte Module wie die vorhandenen Methoden. Teste sie in crates/app-api/tests/api.rs mit dem Helfer api(config()), auch den Fehlerfall.

  3. Führe pnpm types:generate aus, exportiere den neuen Typ aus packages/shared-types/src/index.ts und committe die Dateien in packages/shared-types/src/generated. pnpm types:check schlägt fehl, wenn sie veraltet sind.

  4. Lege den Befehl in der passenden Datei in apps/desktop/src-tauri/src/commands/ an (hier filesystem.rs), nach dem Muster von validate_path: Er nimmt State<'_> und die Argumente und gibt state.api.storage_info() zurück. Registriere ihn in generate_handler! in src-tauri/src/main.rs, deklariere "storage_info" in build.rs und erlaube "allow-storage-info" in capabilities/main-window.json.

  5. Ergänze die Methode im Interface NativeClient in packages/native-client/src/client.ts, in TauriNativeClient in tauri.ts (call<StorageInfoDto>("storage_info"); JavaScript-Argumente sind camelCase, Tauri bildet sie auf snake_case ab) und in MockNativeClient in mock.ts mit realistischen Daten und den Fehlerszenarien. Teste den Mock in mock.test.ts.

  6. Lies den Wert in der UI mit einem Hook unter apps/desktop/src/features/<feature>/hooks/, wie useFeatures: useQuery mit stabilem Schlüssel und useNativeClient(). Zeige Fehler mit i18n.error an.

  7. Ergänze jeden neuen RW_*-Code in packages/i18n/locales/*/errors.json und jeden UI-Text in common.json, in de-DE, en und it-IT. Prüfe das Layout auf Deutsch.

  8. Führe den Befehl in docs/tauri-bridge.md auf.

Fertig, wenn

  • die Prüfbefehle durchlaufen und pnpm types:check keinen Unterschied meldet;
  • der Befehl genau einen Eintrag allow-<name> in der Capability hat und in main.rs und build.rs registriert ist;
  • der Mock die Methode implementiert, damit pnpm dev ohne Rust-Kern funktioniert;
  • jeder neue Code und Text in den drei Sprachen existiert.