aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src-tauri
diff options
context:
space:
mode:
Diffstat (limited to 'src-tauri')
-rw-r--r--src-tauri/Cargo.toml5
-rw-r--r--src-tauri/src/core/account_storage.rs20
-rw-r--r--src-tauri/src/core/assistant.rs30
-rw-r--r--src-tauri/src/core/auth.rs16
-rw-r--r--src-tauri/src/core/config.rs15
-rw-r--r--src-tauri/src/core/downloader.rs37
-rw-r--r--src-tauri/src/core/fabric.rs54
-rw-r--r--src-tauri/src/core/forge.rs10
-rw-r--r--src-tauri/src/core/game_version.rs50
-rw-r--r--src-tauri/src/core/instance.rs15
-rw-r--r--src-tauri/src/core/java/mod.rs20
-rw-r--r--src-tauri/src/core/java/persistence.rs5
-rw-r--r--src-tauri/src/core/java/priority.rs2
-rw-r--r--src-tauri/src/core/java/providers/adoptium.rs25
-rw-r--r--src-tauri/src/core/manifest.rs15
-rw-r--r--src-tauri/src/main.rs85
-rw-r--r--src-tauri/src/utils/api.rs90
-rw-r--r--src-tauri/src/utils/mod.rs2
18 files changed, 247 insertions, 249 deletions
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 28d600a..38ef140 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -19,7 +19,6 @@ assets = [
bytes = "1.11.0"
chrono = "0.4"
dirs = "5.0"
-dropout-core = { path = "../crates/core", version = "0.1.0" }
dropout-macros = { path = "../crates/macros", version = "0.1.0" }
env_logger = "0.9"
flate2 = "1.0"
@@ -49,5 +48,9 @@ ts-rs = { version = "11.1.0", features = ["serde-compat"] }
uuid = { version = "1.10.0", features = ["serde", "v3", "v4"] }
zip = "2.2.2"
+[dev-dependencies]
+ctor = "0.6.3"
+inventory = "0.3.21"
+
[build-dependencies]
tauri-build = { version = "2.0", features = [] }
diff --git a/src-tauri/src/core/account_storage.rs b/src-tauri/src/core/account_storage.rs
index a18b5fc..df202cd 100644
--- a/src-tauri/src/core/account_storage.rs
+++ b/src-tauri/src/core/account_storage.rs
@@ -6,10 +6,7 @@ use ts_rs::TS;
/// Stored account data for persistence
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/account_storage.ts"
-)]
+#[ts(export, export_to = "account.ts")]
pub struct AccountStore {
pub accounts: Vec<StoredAccount>,
pub active_account_id: Option<String>,
@@ -17,10 +14,7 @@ pub struct AccountStore {
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(tag = "type")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/account_storage.ts"
-)]
+#[ts(export, export_to = "account.ts")]
pub enum StoredAccount {
Offline(OfflineAccount),
Microsoft(StoredMicrosoftAccount),
@@ -28,10 +22,7 @@ pub enum StoredAccount {
/// Microsoft account with refresh token for persistence
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/account_storage.ts"
-)]
+#[ts(export, export_to = "account.ts")]
pub struct StoredMicrosoftAccount {
pub username: String,
pub uuid: String,
@@ -78,10 +69,7 @@ impl StoredAccount {
}
#[derive(Debug, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/account_storage.ts"
-)]
+#[ts(export, export_to = "account.ts")]
pub struct AccountStorage {
file_path: PathBuf,
}
diff --git a/src-tauri/src/core/assistant.rs b/src-tauri/src/core/assistant.rs
index 6e656dc..5663007 100644
--- a/src-tauri/src/core/assistant.rs
+++ b/src-tauri/src/core/assistant.rs
@@ -8,10 +8,7 @@ use ts_rs::TS;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/assistant.ts"
-)]
+#[ts(export, export_to = "assistant.ts")]
pub struct Message {
pub role: String,
pub content: String,
@@ -59,10 +56,7 @@ pub struct OllamaTagsResponse {
// Simplified model info for frontend
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/assistant.ts"
-)]
+#[ts(export, export_to = "assistant.ts")]
pub struct ModelInfo {
pub id: String,
pub name: String,
@@ -115,10 +109,7 @@ pub struct OpenAIModelsResponse {
// Streaming response structures
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/assistant.ts"
-)]
+#[ts(export, export_to = "assistant.ts")]
pub struct GenerationStats {
pub total_duration: u64,
pub load_duration: u64,
@@ -130,10 +121,7 @@ pub struct GenerationStats {
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/assistant.ts"
-)]
+#[ts(export, export_to = "assistant.ts")]
pub struct StreamChunk {
pub content: String,
pub done: bool,
@@ -244,7 +232,10 @@ impl GameAssistant {
// Add language instruction if not auto
if config.response_language != "auto" {
- system_content = format!("{}\n\nIMPORTANT: Respond in {}. Do not include Pinyin or English translations unless explicitly requested.", system_content, config.response_language);
+ system_content = format!(
+ "{}\n\nIMPORTANT: Respond in {}. Do not include Pinyin or English translations unless explicitly requested.",
+ system_content, config.response_language
+ );
}
// Add log context if available
@@ -456,7 +447,10 @@ impl GameAssistant {
let mut system_content = config.system_prompt.clone();
if config.response_language != "auto" {
- system_content = format!("{}\n\nIMPORTANT: Respond in {}. Do not include Pinyin or English translations unless explicitly requested.", system_content, config.response_language);
+ system_content = format!(
+ "{}\n\nIMPORTANT: Respond in {}. Do not include Pinyin or English translations unless explicitly requested.",
+ system_content, config.response_language
+ );
}
if !context.is_empty() {
diff --git a/src-tauri/src/core/auth.rs b/src-tauri/src/core/auth.rs
index 0e873e3..b137957 100644
--- a/src-tauri/src/core/auth.rs
+++ b/src-tauri/src/core/auth.rs
@@ -15,11 +15,7 @@ fn get_client() -> reqwest::Client {
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(tag = "type")]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- tag = "type",
- export_to = "../../packages/ui-new/src/types/bindings/auth.ts"
-)]
+#[ts(export, tag = "type", export_to = "auth.ts")]
pub enum Account {
Offline(OfflineAccount),
Microsoft(MicrosoftAccount),
@@ -50,7 +46,7 @@ impl Account {
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/auth.ts")]
+#[ts(export, export_to = "auth.ts")]
pub struct OfflineAccount {
pub username: String,
pub uuid: String,
@@ -58,7 +54,7 @@ pub struct OfflineAccount {
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/auth.ts")]
+#[ts(export, export_to = "auth.ts")]
pub struct MicrosoftAccount {
pub username: String,
pub uuid: String,
@@ -89,7 +85,7 @@ const SCOPE: &str = "XboxLive.SignIn XboxLive.offline_access";
#[derive(Debug, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/auth.ts")]
+#[ts(export, export_to = "auth.ts")]
pub struct DeviceCodeResponse {
pub user_code: String,
pub device_code: String,
@@ -101,7 +97,7 @@ pub struct DeviceCodeResponse {
#[derive(Debug, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/auth.ts")]
+#[ts(export, export_to = "auth.ts")]
pub struct TokenResponse {
pub access_token: String,
pub refresh_token: Option<String>,
@@ -225,7 +221,7 @@ pub struct MinecraftAuthResponse {
#[derive(Debug, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/auth.ts")]
+#[ts(export, export_to = "auth.ts")]
pub struct MinecraftProfile {
pub id: String,
pub name: String,
diff --git a/src-tauri/src/core/config.rs b/src-tauri/src/core/config.rs
index 0d0e8ff..d1f306a 100644
--- a/src-tauri/src/core/config.rs
+++ b/src-tauri/src/core/config.rs
@@ -7,10 +7,7 @@ use ts_rs::TS;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/config.ts"
-)]
+#[ts(export, export_to = "config.ts")]
#[serde(default)]
pub struct AssistantConfig {
pub enabled: bool,
@@ -51,10 +48,7 @@ impl Default for AssistantConfig {
/// Feature-gated arguments configuration
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/config.ts"
-)]
+#[ts(export, export_to = "config.ts")]
#[serde(default)]
pub struct FeatureFlags {
/// Demo user: enables demo-related arguments when rules require it
@@ -83,10 +77,7 @@ impl Default for FeatureFlags {
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/config.ts"
-)]
+#[ts(export, export_to = "config.ts")]
#[serde(default)]
pub struct LauncherConfig {
pub min_memory: u32, // in MB
diff --git a/src-tauri/src/core/downloader.rs b/src-tauri/src/core/downloader.rs
index d4fc782..a6b11c5 100644
--- a/src-tauri/src/core/downloader.rs
+++ b/src-tauri/src/core/downloader.rs
@@ -2,8 +2,8 @@ use futures::StreamExt;
use serde::{Deserialize, Serialize};
use sha1::Digest as Sha1Digest;
use std::path::PathBuf;
-use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
use std::sync::Arc;
+use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
use tauri::{AppHandle, Emitter, Manager, Window};
use tokio::io::{AsyncSeekExt, AsyncWriteExt};
use tokio::sync::Semaphore;
@@ -11,10 +11,7 @@ use ts_rs::TS;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/downloader.ts"
-)]
+#[ts(export, export_to = "downloader.ts")]
pub struct DownloadTask {
pub url: String,
pub path: PathBuf,
@@ -27,10 +24,7 @@ pub struct DownloadTask {
/// Metadata for resumable downloads stored in .part.meta file
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/downloader.ts"
-)]
+#[ts(export, export_to = "downloader.ts")]
pub struct DownloadMetadata {
pub url: String,
pub file_name: String,
@@ -44,10 +38,7 @@ pub struct DownloadMetadata {
/// A download segment for multi-segment parallel downloading
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/downloader.ts"
-)]
+#[ts(export, export_to = "downloader.ts")]
pub struct DownloadSegment {
pub start: u64,
pub end: u64,
@@ -58,10 +49,7 @@ pub struct DownloadSegment {
/// Progress event for Java download
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/downloader.ts"
-)]
+#[ts(export, export_to = "downloader.ts")]
pub struct JavaDownloadProgress {
pub file_name: String,
pub downloaded_bytes: u64,
@@ -75,10 +63,7 @@ pub struct JavaDownloadProgress {
/// Pending download task for queue persistence
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/downloader.ts"
-)]
+#[ts(export, export_to = "downloader.ts")]
pub struct PendingJavaDownload {
pub major_version: u32,
pub image_type: String,
@@ -93,10 +78,7 @@ pub struct PendingJavaDownload {
/// Download queue for persistence
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/downloader.ts"
-)]
+#[ts(export, export_to = "downloader.ts")]
pub struct DownloadQueue {
pub pending_downloads: Vec<PendingJavaDownload>,
}
@@ -452,10 +434,7 @@ fn create_new_metadata(
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui/src/types/generated/downloader.ts"
-)]
+#[ts(export, export_to = "downloader.ts")]
pub struct ProgressEvent {
pub file: String,
pub downloaded: u64,
diff --git a/src-tauri/src/core/fabric.rs b/src-tauri/src/core/fabric.rs
index 7385850..a6ef236 100644
--- a/src-tauri/src/core/fabric.rs
+++ b/src-tauri/src/core/fabric.rs
@@ -15,10 +15,7 @@ const FABRIC_META_URL: &str = "https://meta.fabricmc.net/v2";
/// Represents a Fabric loader version from the Meta API.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/fabric.ts"
-)]
+#[ts(export, export_to = "fabric.ts")]
pub struct FabricLoaderVersion {
pub separator: String,
pub build: i32,
@@ -30,10 +27,7 @@ pub struct FabricLoaderVersion {
/// Represents a Fabric intermediary mapping version.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/fabric.ts"
-)]
+#[ts(export, export_to = "fabric.ts")]
pub struct FabricIntermediaryVersion {
pub maven: String,
pub version: String,
@@ -43,10 +37,7 @@ pub struct FabricIntermediaryVersion {
/// Represents a combined loader + intermediary version entry.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/fabric.ts"
-)]
+#[ts(export, export_to = "fabric.ts")]
pub struct FabricLoaderEntry {
pub loader: FabricLoaderVersion,
pub intermediary: FabricIntermediaryVersion,
@@ -57,10 +48,7 @@ pub struct FabricLoaderEntry {
/// Launcher metadata from Fabric Meta API.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/fabric.ts"
-)]
+#[ts(export, export_to = "fabric.ts")]
pub struct FabricLauncherMeta {
pub version: i32,
pub libraries: FabricLibraries,
@@ -71,10 +59,7 @@ pub struct FabricLauncherMeta {
/// Libraries required by Fabric loader.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/fabric.ts"
-)]
+#[ts(export, export_to = "fabric.ts")]
pub struct FabricLibraries {
pub client: Vec<FabricLibrary>,
pub common: Vec<FabricLibrary>,
@@ -84,10 +69,7 @@ pub struct FabricLibraries {
/// A single Fabric library dependency.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/fabric.ts"
-)]
+#[ts(export, export_to = "fabric.ts")]
pub struct FabricLibrary {
pub name: String,
pub url: Option<String>,
@@ -97,11 +79,7 @@ pub struct FabricLibrary {
/// Can be either a struct with client/server fields or a simple string.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/fabric.ts",
- untagged
-)]
+#[ts(export, export_to = "fabric.ts", untagged)]
#[serde(untagged)]
pub enum FabricMainClass {
Structured { client: String, server: String },
@@ -128,10 +106,7 @@ impl FabricMainClass {
/// Represents a Minecraft version supported by Fabric.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/fabric.ts"
-)]
+#[ts(export, export_to = "fabric.ts")]
pub struct FabricGameVersion {
pub version: String,
pub stable: bool,
@@ -140,10 +115,7 @@ pub struct FabricGameVersion {
/// Information about an installed Fabric version.
#[derive(Debug, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/fabric.ts"
-)]
+#[ts(export, export_to = "fabric.ts")]
pub struct InstalledFabricVersion {
pub id: String,
pub minecraft_version: String,
@@ -155,8 +127,8 @@ pub struct InstalledFabricVersion {
///
/// # Returns
/// A list of game versions that have Fabric intermediary mappings available.
-pub async fn fetch_supported_game_versions(
-) -> Result<Vec<FabricGameVersion>, Box<dyn Error + Send + Sync>> {
+pub async fn fetch_supported_game_versions()
+-> Result<Vec<FabricGameVersion>, Box<dyn Error + Send + Sync>> {
let url = format!("{}/versions/game", FABRIC_META_URL);
let resp = reqwest::get(&url)
.await?
@@ -169,8 +141,8 @@ pub async fn fetch_supported_game_versions(
///
/// # Returns
/// A list of all Fabric loader versions, ordered by build number (newest first).
-pub async fn fetch_loader_versions(
-) -> Result<Vec<FabricLoaderVersion>, Box<dyn Error + Send + Sync>> {
+pub async fn fetch_loader_versions()
+-> Result<Vec<FabricLoaderVersion>, Box<dyn Error + Send + Sync>> {
let url = format!("{}/versions/loader", FABRIC_META_URL);
let resp = reqwest::get(&url)
.await?
diff --git a/src-tauri/src/core/forge.rs b/src-tauri/src/core/forge.rs
index 1d4ae1d..4452f8e 100644
--- a/src-tauri/src/core/forge.rs
+++ b/src-tauri/src/core/forge.rs
@@ -22,10 +22,7 @@ const FORGE_FILES_URL: &str = "https://files.minecraftforge.net/";
/// Represents a Forge version entry.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/forge.ts"
-)]
+#[ts(export, export_to = "forge.ts")]
pub struct ForgeVersion {
pub version: String,
pub minecraft_version: String,
@@ -44,10 +41,7 @@ struct ForgePromotions {
/// Information about an installed Forge version.
#[derive(Debug, Serialize, Clone, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/forge.ts"
-)]
+#[ts(export, export_to = "forge.ts")]
pub struct InstalledForgeVersion {
pub id: String,
pub minecraft_version: String,
diff --git a/src-tauri/src/core/game_version.rs b/src-tauri/src/core/game_version.rs
index 7df631a..82196bd 100644
--- a/src-tauri/src/core/game_version.rs
+++ b/src-tauri/src/core/game_version.rs
@@ -4,10 +4,7 @@ use ts_rs::TS;
/// Represents a Minecraft version JSON, supporting both vanilla and modded (Fabric/Forge) formats.
/// Modded versions use `inheritsFrom` to reference a parent vanilla version.
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct GameVersion {
pub id: String,
/// Optional for mod loaders that inherit from vanilla
@@ -34,20 +31,14 @@ pub struct GameVersion {
}
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct Downloads {
pub client: DownloadArtifact,
pub server: Option<DownloadArtifact>,
}
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct DownloadArtifact {
pub sha1: Option<String>,
pub size: Option<u64>,
@@ -56,10 +47,7 @@ pub struct DownloadArtifact {
}
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct AssetIndex {
pub id: String,
pub sha1: String,
@@ -70,10 +58,7 @@ pub struct AssetIndex {
}
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct Library {
pub downloads: Option<LibraryDownloads>,
pub name: String,
@@ -85,10 +70,7 @@ pub struct Library {
}
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct Rule {
pub action: String, // "allow" or "disallow"
pub os: Option<OsRule>,
@@ -97,10 +79,7 @@ pub struct Rule {
}
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct OsRule {
pub name: Option<String>, // "linux", "osx", "windows"
pub version: Option<String>, // Regex
@@ -108,10 +87,7 @@ pub struct OsRule {
}
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct LibraryDownloads {
pub artifact: Option<DownloadArtifact>,
#[ts(type = "Record<string, unknown>")]
@@ -119,10 +95,7 @@ pub struct LibraryDownloads {
}
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct Arguments {
#[ts(type = "Record<string, unknown>")]
pub game: Option<serde_json::Value>,
@@ -131,10 +104,7 @@ pub struct Arguments {
}
#[derive(Debug, Deserialize, Serialize, Clone, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/game_version.ts"
-)]
+#[ts(export, export_to = "game-version.ts")]
pub struct JavaVersion {
pub component: String,
#[serde(rename = "majorVersion")]
diff --git a/src-tauri/src/core/instance.rs b/src-tauri/src/core/instance.rs
index e842ec9..0237270 100644
--- a/src-tauri/src/core/instance.rs
+++ b/src-tauri/src/core/instance.rs
@@ -16,10 +16,7 @@ use ts_rs::TS;
/// Represents a game instance/profile
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/instance.ts"
-)]
+#[ts(export, export_to = "instance.ts")]
pub struct Instance {
pub id: String, // 唯一标识符(UUID)
pub name: String, // 显示名称
@@ -40,10 +37,7 @@ pub struct Instance {
/// Memory settings override for an instance
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/instance.ts"
-)]
+#[ts(export, export_to = "instance.ts")]
pub struct MemoryOverride {
pub min: u32, // MB
pub max: u32, // MB
@@ -52,10 +46,7 @@ pub struct MemoryOverride {
/// Configuration for all instances
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/instance.ts"
-)]
+#[ts(export, export_to = "instance.ts")]
pub struct InstanceConfig {
pub instances: Vec<Instance>,
pub active_instance_id: Option<String>, // 当前活动的实例ID
diff --git a/src-tauri/src/core/java/mod.rs b/src-tauri/src/core/java/mod.rs
index 2215872..c8d936d 100644
--- a/src-tauri/src/core/java/mod.rs
+++ b/src-tauri/src/core/java/mod.rs
@@ -33,10 +33,7 @@ use providers::AdoptiumProvider;
const CACHE_DURATION_SECS: u64 = 24 * 60 * 60;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/index.ts"
-)]
+#[ts(export, export_to = "java/core.ts")]
pub struct JavaInstallation {
pub path: String,
pub version: String,
@@ -69,10 +66,7 @@ impl std::fmt::Display for ImageType {
}
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/index.ts"
-)]
+#[ts(export, export_to = "java/core.ts")]
pub struct JavaReleaseInfo {
pub major_version: u32,
pub image_type: String,
@@ -88,10 +82,7 @@ pub struct JavaReleaseInfo {
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/index.ts"
-)]
+#[ts(export, export_to = "java/core.ts")]
pub struct JavaCatalog {
pub releases: Vec<JavaReleaseInfo>,
pub available_major_versions: Vec<u32>,
@@ -100,10 +91,7 @@ pub struct JavaCatalog {
}
#[derive(Debug, Clone, Serialize, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/index.ts"
-)]
+#[ts(export, export_to = "java/core.ts")]
pub struct JavaDownloadInfo {
pub version: String, // e.g., "17.0.2+8"
pub release_name: String, // e.g., "jdk-17.0.2+8"
diff --git a/src-tauri/src/core/java/persistence.rs b/src-tauri/src/core/java/persistence.rs
index 6720696..a6727d7 100644
--- a/src-tauri/src/core/java/persistence.rs
+++ b/src-tauri/src/core/java/persistence.rs
@@ -5,10 +5,7 @@ use tauri::{AppHandle, Manager};
use ts_rs::TS;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/persistence.ts"
-)]
+#[ts(export, export_to = "java/persistence.ts")]
pub struct JavaConfig {
pub user_defined_paths: Vec<String>,
pub preferred_java_path: Option<String>,
diff --git a/src-tauri/src/core/java/priority.rs b/src-tauri/src/core/java/priority.rs
index b2e9fb4..f991eb7 100644
--- a/src-tauri/src/core/java/priority.rs
+++ b/src-tauri/src/core/java/priority.rs
@@ -1,8 +1,8 @@
use tauri::AppHandle;
+use crate::core::java::JavaInstallation;
use crate::core::java::persistence;
use crate::core::java::validation;
-use crate::core::java::JavaInstallation;
pub async fn resolve_java_for_launch(
app_handle: &AppHandle,
diff --git a/src-tauri/src/core/java/providers/adoptium.rs b/src-tauri/src/core/java/providers/adoptium.rs
index 20fb2d5..1765a99 100644
--- a/src-tauri/src/core/java/providers/adoptium.rs
+++ b/src-tauri/src/core/java/providers/adoptium.rs
@@ -9,10 +9,7 @@ use ts_rs::TS;
const ADOPTIUM_API_BASE: &str = "https://api.adoptium.net/v3";
#[derive(Debug, Clone, Deserialize, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/providers/adoptium.ts"
-)]
+#[ts(export, export_to = "java/providers/adoptium.ts")]
pub struct AdoptiumAsset {
pub binary: AdoptiumBinary,
pub release_name: String,
@@ -21,10 +18,7 @@ pub struct AdoptiumAsset {
#[derive(Debug, Clone, Deserialize, TS)]
#[allow(dead_code)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/providers/adoptium.ts"
-)]
+#[ts(export, export_to = "java/providers/adoptium.ts")]
pub struct AdoptiumBinary {
pub os: String,
pub architecture: String,
@@ -35,10 +29,7 @@ pub struct AdoptiumBinary {
}
#[derive(Debug, Clone, Deserialize, TS)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/providers/adoptium.ts"
-)]
+#[ts(export, export_to = "java/providers/adoptium.ts")]
pub struct AdoptiumPackage {
pub name: String,
pub link: String,
@@ -48,10 +39,7 @@ pub struct AdoptiumPackage {
#[derive(Debug, Clone, Deserialize, TS)]
#[allow(dead_code)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/providers/adoptium.ts"
-)]
+#[ts(export, export_to = "java/providers/adoptium.ts")]
pub struct AdoptiumVersionData {
pub major: u32,
pub minor: u32,
@@ -62,10 +50,7 @@ pub struct AdoptiumVersionData {
#[derive(Debug, Clone, Deserialize, TS)]
#[allow(dead_code)]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/java/providers/adoptium.ts"
-)]
+#[ts(export, export_to = "java/providers/adoptium.ts")]
pub struct AvailableReleases {
pub available_releases: Vec<u32>,
pub available_lts_releases: Vec<u32>,
diff --git a/src-tauri/src/core/manifest.rs b/src-tauri/src/core/manifest.rs
index 9e4cb4e..d40d958 100644
--- a/src-tauri/src/core/manifest.rs
+++ b/src-tauri/src/core/manifest.rs
@@ -7,10 +7,7 @@ use ts_rs::TS;
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/manifest.ts"
-)]
+#[ts(export, export_to = "manifest.ts")]
pub struct VersionManifest {
pub latest: Latest,
pub versions: Vec<Version>,
@@ -18,10 +15,7 @@ pub struct VersionManifest {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/manifest.ts"
-)]
+#[ts(export, export_to = "manifest.ts")]
pub struct Latest {
pub release: String,
pub snapshot: String,
@@ -29,10 +23,7 @@ pub struct Latest {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
-#[ts(
- export,
- export_to = "../../packages/ui-new/src/types/bindings/manifest.ts"
-)]
+#[ts(export, export_to = "manifest.ts")]
pub struct Version {
pub id: String,
#[serde(rename = "type")]
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index f652012..e51d49f 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -6,7 +6,8 @@ use std::process::Stdio;
use std::sync::Mutex;
use tauri::{Emitter, Manager, State, Window}; // Added Emitter
use tokio::io::{AsyncBufReadExt, BufReader};
-use tokio::process::Command; // Added Serialize
+use tokio::process::Command;
+use ts_rs::TS; // Added Serialize
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;
@@ -63,6 +64,7 @@ fn has_unresolved_placeholder(s: &str) -> bool {
}
#[tauri::command]
+#[dropout_macros::api]
async fn start_game(
window: Window,
auth_state: State<'_, core::auth::AccountState>,
@@ -941,6 +943,7 @@ async fn get_versions(
/// Check if a version is installed (has client.jar)
#[tauri::command]
+#[dropout_macros::api]
async fn check_version_installed(
_window: Window,
instance_state: State<'_, core::instance::InstanceState>,
@@ -980,6 +983,7 @@ async fn check_version_installed(
/// Install a version (download client, libraries, assets) without launching
#[tauri::command]
+#[dropout_macros::api]
async fn install_version(
window: Window,
config_state: State<'_, core::config::ConfigState>,
@@ -1303,6 +1307,7 @@ async fn install_version(
}
#[tauri::command]
+#[dropout_macros::api]
async fn login_offline(
window: Window,
state: State<'_, core::auth::AccountState>,
@@ -1326,6 +1331,7 @@ async fn login_offline(
}
#[tauri::command]
+#[dropout_macros::api]
async fn get_active_account(
state: State<'_, core::auth::AccountState>,
) -> Result<Option<core::auth::Account>, String> {
@@ -1333,6 +1339,7 @@ async fn get_active_account(
}
#[tauri::command]
+#[dropout_macros::api]
async fn logout(window: Window, state: State<'_, core::auth::AccountState>) -> Result<(), String> {
// Get current account UUID before clearing
let uuid = state
@@ -1359,6 +1366,7 @@ async fn logout(window: Window, state: State<'_, core::auth::AccountState>) -> R
}
#[tauri::command]
+#[dropout_macros::api]
async fn get_settings(
state: State<'_, core::config::ConfigState>,
) -> Result<core::config::LauncherConfig, String> {
@@ -1366,6 +1374,7 @@ async fn get_settings(
}
#[tauri::command]
+#[dropout_macros::api]
async fn save_settings(
state: State<'_, core::config::ConfigState>,
config: core::config::LauncherConfig,
@@ -1376,11 +1385,13 @@ async fn save_settings(
}
#[tauri::command]
+#[dropout_macros::api]
async fn get_config_path(state: State<'_, core::config::ConfigState>) -> Result<String, String> {
Ok(state.file_path.to_string_lossy().to_string())
}
#[tauri::command]
+#[dropout_macros::api]
async fn read_raw_config(state: State<'_, core::config::ConfigState>) -> Result<String, String> {
tokio::fs::read_to_string(&state.file_path)
.await
@@ -1388,6 +1399,7 @@ async fn read_raw_config(state: State<'_, core::config::ConfigState>) -> Result<
}
#[tauri::command]
+#[dropout_macros::api]
async fn save_raw_config(
state: State<'_, core::config::ConfigState>,
content: String,
@@ -1408,11 +1420,13 @@ async fn save_raw_config(
}
#[tauri::command]
+#[dropout_macros::api]
async fn start_microsoft_login() -> Result<core::auth::DeviceCodeResponse, String> {
core::auth::start_device_flow().await
}
#[tauri::command]
+#[dropout_macros::api]
async fn complete_microsoft_login(
window: Window,
state: State<'_, core::auth::AccountState>,
@@ -1483,6 +1497,7 @@ async fn complete_microsoft_login(
/// Refresh token for current Microsoft account
#[tauri::command]
+#[dropout_macros::api]
async fn refresh_account(
window: Window,
state: State<'_, core::auth::AccountState>,
@@ -1518,6 +1533,7 @@ async fn refresh_account(
/// Detect Java installations on the system
#[tauri::command]
+#[dropout_macros::api]
async fn detect_all_java_installations(
app_handle: tauri::AppHandle,
) -> Result<Vec<core::java::JavaInstallation>, String> {
@@ -1526,6 +1542,7 @@ async fn detect_all_java_installations(
/// Alias for detect_all_java_installations (for backward compatibility)
#[tauri::command]
+#[dropout_macros::api]
async fn detect_java(
app_handle: tauri::AppHandle,
) -> Result<Vec<core::java::JavaInstallation>, String> {
@@ -1534,6 +1551,7 @@ async fn detect_java(
/// Get recommended Java for a specific Minecraft version
#[tauri::command]
+#[dropout_macros::api]
async fn get_recommended_java(
required_major_version: Option<u64>,
) -> Result<Option<core::java::JavaInstallation>, String> {
@@ -1542,6 +1560,7 @@ async fn get_recommended_java(
/// Get Adoptium Java download info
#[tauri::command]
+#[dropout_macros::api]
async fn fetch_adoptium_java(
major_version: u32,
image_type: String,
@@ -1557,6 +1576,7 @@ async fn fetch_adoptium_java(
/// Download and install Adoptium Java
#[tauri::command]
+#[dropout_macros::api]
async fn download_adoptium_java(
app_handle: tauri::AppHandle,
major_version: u32,
@@ -1575,6 +1595,7 @@ async fn download_adoptium_java(
/// Get available Adoptium Java versions
#[tauri::command]
+#[dropout_macros::api]
async fn fetch_available_java_versions() -> Result<Vec<u32>, String> {
core::java::fetch_available_versions()
.await
@@ -1583,6 +1604,7 @@ async fn fetch_available_java_versions() -> Result<Vec<u32>, String> {
/// Fetch Java catalog with platform availability (uses cache)
#[tauri::command]
+#[dropout_macros::api]
async fn fetch_java_catalog(
app_handle: tauri::AppHandle,
) -> Result<core::java::JavaCatalog, String> {
@@ -1593,6 +1615,7 @@ async fn fetch_java_catalog(
/// Refresh Java catalog (bypass cache)
#[tauri::command]
+#[dropout_macros::api]
async fn refresh_java_catalog(
app_handle: tauri::AppHandle,
) -> Result<core::java::JavaCatalog, String> {
@@ -1603,6 +1626,7 @@ async fn refresh_java_catalog(
/// Cancel current Java download
#[tauri::command]
+#[dropout_macros::api]
async fn cancel_java_download() -> Result<(), String> {
core::java::cancel_current_download();
Ok(())
@@ -1610,6 +1634,7 @@ async fn cancel_java_download() -> Result<(), String> {
/// Get pending Java downloads
#[tauri::command]
+#[dropout_macros::api]
async fn get_pending_java_downloads(
app_handle: tauri::AppHandle,
) -> Result<Vec<core::downloader::PendingJavaDownload>, String> {
@@ -1618,6 +1643,7 @@ async fn get_pending_java_downloads(
/// Resume pending Java downloads
#[tauri::command]
+#[dropout_macros::api]
async fn resume_java_downloads(
app_handle: tauri::AppHandle,
) -> Result<Vec<core::java::JavaInstallation>, String> {
@@ -1626,6 +1652,7 @@ async fn resume_java_downloads(
/// Get Minecraft versions supported by Fabric
#[tauri::command]
+#[dropout_macros::api]
async fn get_fabric_game_versions() -> Result<Vec<core::fabric::FabricGameVersion>, String> {
core::fabric::fetch_supported_game_versions()
.await
@@ -1634,6 +1661,7 @@ async fn get_fabric_game_versions() -> Result<Vec<core::fabric::FabricGameVersio
/// Get available Fabric loader versions
#[tauri::command]
+#[dropout_macros::api]
async fn get_fabric_loader_versions() -> Result<Vec<core::fabric::FabricLoaderVersion>, String> {
core::fabric::fetch_loader_versions()
.await
@@ -1642,6 +1670,7 @@ async fn get_fabric_loader_versions() -> Result<Vec<core::fabric::FabricLoaderVe
/// Get Fabric loaders available for a specific Minecraft version
#[tauri::command]
+#[dropout_macros::api]
async fn get_fabric_loaders_for_version(
game_version: String,
) -> Result<Vec<core::fabric::FabricLoaderEntry>, String> {
@@ -1652,6 +1681,7 @@ async fn get_fabric_loaders_for_version(
/// Install Fabric loader for a specific Minecraft version
#[tauri::command]
+#[dropout_macros::api]
async fn install_fabric(
window: Window,
instance_state: State<'_, core::instance::InstanceState>,
@@ -1696,6 +1726,7 @@ async fn install_fabric(
/// List installed Fabric versions
#[tauri::command]
+#[dropout_macros::api]
async fn list_installed_fabric_versions(
_window: Window,
instance_state: State<'_, core::instance::InstanceState>,
@@ -1712,6 +1743,7 @@ async fn list_installed_fabric_versions(
/// Get Java version requirement for a specific version
#[tauri::command]
+#[dropout_macros::api]
async fn get_version_java_version(
_window: Window,
instance_state: State<'_, core::instance::InstanceState>,
@@ -1730,17 +1762,18 @@ async fn get_version_java_version(
}
/// Version metadata for display in the UI
-#[derive(serde::Serialize)]
+#[derive(serde::Serialize, TS)]
+#[serde(rename_all = "camelCase")]
+#[ts(export, export_to = "core.ts")]
struct VersionMetadata {
id: String,
- #[serde(rename = "javaVersion")]
java_version: Option<u64>,
- #[serde(rename = "isInstalled")]
is_installed: bool,
}
/// Delete a version (remove version directory)
#[tauri::command]
+#[dropout_macros::api]
async fn delete_version(
window: Window,
instance_state: State<'_, core::instance::InstanceState>,
@@ -1795,6 +1828,7 @@ async fn delete_version(
/// Get detailed metadata for a specific version
#[tauri::command]
+#[dropout_macros::api]
async fn get_version_metadata(
_window: Window,
instance_state: State<'_, core::instance::InstanceState>,
@@ -1880,7 +1914,9 @@ async fn get_version_metadata(
}
/// Installed version info
-#[derive(serde::Serialize)]
+#[derive(serde::Serialize, TS)]
+#[serde(rename_all = "camelCase")]
+#[ts(export, export_to = "core.ts")]
struct InstalledVersion {
id: String,
#[serde(rename = "type")]
@@ -1890,6 +1926,7 @@ struct InstalledVersion {
/// List all installed versions from the data directory
/// Simply lists all folders in the versions directory without validation
#[tauri::command]
+#[dropout_macros::api]
async fn list_installed_versions(
_window: Window,
instance_state: State<'_, core::instance::InstanceState>,
@@ -1976,6 +2013,7 @@ async fn list_installed_versions(
/// Check if Fabric is installed for a specific version
#[tauri::command]
+#[dropout_macros::api]
async fn is_fabric_installed(
_window: Window,
instance_state: State<'_, core::instance::InstanceState>,
@@ -1996,6 +2034,7 @@ async fn is_fabric_installed(
/// Get Minecraft versions supported by Forge
#[tauri::command]
+#[dropout_macros::api]
async fn get_forge_game_versions() -> Result<Vec<String>, String> {
core::forge::fetch_supported_game_versions()
.await
@@ -2004,6 +2043,7 @@ async fn get_forge_game_versions() -> Result<Vec<String>, String> {
/// Get available Forge versions for a specific Minecraft version
#[tauri::command]
+#[dropout_macros::api]
async fn get_forge_versions_for_game(
game_version: String,
) -> Result<Vec<core::forge::ForgeVersion>, String> {
@@ -2014,6 +2054,7 @@ async fn get_forge_versions_for_game(
/// Install Forge for a specific Minecraft version
#[tauri::command]
+#[dropout_macros::api]
async fn install_forge(
window: Window,
config_state: State<'_, core::config::ConfigState>,
@@ -2109,7 +2150,9 @@ async fn install_forge(
Ok(result)
}
-#[derive(serde::Serialize)]
+#[derive(serde::Serialize, TS)]
+#[serde(rename_all = "camelCase")]
+#[ts(export, export_to = "core.ts")]
struct GithubRelease {
tag_name: String,
name: String,
@@ -2119,6 +2162,7 @@ struct GithubRelease {
}
#[tauri::command]
+#[dropout_macros::api]
async fn get_github_releases() -> Result<Vec<GithubRelease>, String> {
let client = reqwest::Client::new();
let res = client
@@ -2155,12 +2199,14 @@ async fn get_github_releases() -> Result<Vec<GithubRelease>, String> {
Ok(result)
}
-#[derive(Serialize)]
+#[derive(Serialize, TS)]
+#[ts(export, export_to = "core.ts")]
struct PastebinResponse {
url: String,
}
#[tauri::command]
+#[dropout_macros::api]
async fn upload_to_pastebin(
state: State<'_, core::config::ConfigState>,
content: String,
@@ -2230,6 +2276,7 @@ async fn upload_to_pastebin(
}
#[tauri::command]
+#[dropout_macros::api]
async fn assistant_check_health(
assistant_state: State<'_, core::assistant::AssistantState>,
config_state: State<'_, core::config::ConfigState>,
@@ -2240,6 +2287,7 @@ async fn assistant_check_health(
}
#[tauri::command]
+#[dropout_macros::api]
async fn assistant_chat(
assistant_state: State<'_, core::assistant::AssistantState>,
config_state: State<'_, core::config::ConfigState>,
@@ -2251,6 +2299,7 @@ async fn assistant_chat(
}
#[tauri::command]
+#[dropout_macros::api]
async fn list_ollama_models(
assistant_state: State<'_, core::assistant::AssistantState>,
endpoint: String,
@@ -2260,6 +2309,7 @@ async fn list_ollama_models(
}
#[tauri::command]
+#[dropout_macros::api]
async fn list_openai_models(
assistant_state: State<'_, core::assistant::AssistantState>,
config_state: State<'_, core::config::ConfigState>,
@@ -2273,6 +2323,7 @@ async fn list_openai_models(
/// Create a new instance
#[tauri::command]
+#[dropout_macros::api]
async fn create_instance(
window: Window,
state: State<'_, core::instance::InstanceState>,
@@ -2284,6 +2335,7 @@ async fn create_instance(
/// Delete an instance
#[tauri::command]
+#[dropout_macros::api]
async fn delete_instance(
state: State<'_, core::instance::InstanceState>,
instance_id: String,
@@ -2293,6 +2345,7 @@ async fn delete_instance(
/// Update an instance
#[tauri::command]
+#[dropout_macros::api]
async fn update_instance(
state: State<'_, core::instance::InstanceState>,
instance: core::instance::Instance,
@@ -2302,6 +2355,7 @@ async fn update_instance(
/// Get all instances
#[tauri::command]
+#[dropout_macros::api]
async fn list_instances(
state: State<'_, core::instance::InstanceState>,
) -> Result<Vec<core::instance::Instance>, String> {
@@ -2310,6 +2364,7 @@ async fn list_instances(
/// Get a single instance by ID
#[tauri::command]
+#[dropout_macros::api]
async fn get_instance(
state: State<'_, core::instance::InstanceState>,
instance_id: String,
@@ -2321,6 +2376,7 @@ async fn get_instance(
/// Set the active instance
#[tauri::command]
+#[dropout_macros::api]
async fn set_active_instance(
state: State<'_, core::instance::InstanceState>,
instance_id: String,
@@ -2330,6 +2386,7 @@ async fn set_active_instance(
/// Get the active instance
#[tauri::command]
+#[dropout_macros::api]
async fn get_active_instance(
state: State<'_, core::instance::InstanceState>,
) -> Result<Option<core::instance::Instance>, String> {
@@ -2338,6 +2395,7 @@ async fn get_active_instance(
/// Duplicate an instance
#[tauri::command]
+#[dropout_macros::api]
async fn duplicate_instance(
window: Window,
state: State<'_, core::instance::InstanceState>,
@@ -2349,6 +2407,7 @@ async fn duplicate_instance(
}
#[tauri::command]
+#[dropout_macros::api]
async fn assistant_chat_stream(
window: tauri::Window,
assistant_state: State<'_, core::assistant::AssistantState>,
@@ -2363,7 +2422,9 @@ async fn assistant_chat_stream(
}
/// Migrate instance caches to shared global caches
-#[derive(Serialize)]
+#[derive(Serialize, TS)]
+#[serde(rename_all = "camelCase")]
+#[ts(export, export_to = "core.ts")]
struct MigrationResult {
moved_files: usize,
hardlinks: usize,
@@ -2373,6 +2434,7 @@ struct MigrationResult {
}
#[tauri::command]
+#[dropout_macros::api]
async fn migrate_shared_caches(
window: Window,
instance_state: State<'_, core::instance::InstanceState>,
@@ -2412,7 +2474,9 @@ async fn migrate_shared_caches(
}
/// File information for instance file browser
-#[derive(Debug, Clone, Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize, TS)]
+#[serde(rename_all = "camelCase")]
+#[ts(export, export_to = "core.ts")]
struct FileInfo {
name: String,
path: String,
@@ -2423,6 +2487,7 @@ struct FileInfo {
/// List files in an instance subdirectory (mods, resourcepacks, shaderpacks, saves, screenshots)
#[tauri::command]
+#[dropout_macros::api]
async fn list_instance_directory(
instance_state: State<'_, core::instance::InstanceState>,
instance_id: String,
@@ -2474,6 +2539,7 @@ async fn list_instance_directory(
/// Delete a file in an instance directory
#[tauri::command]
+#[dropout_macros::api]
async fn delete_instance_file(path: String) -> Result<(), String> {
let path_buf = std::path::PathBuf::from(&path);
if path_buf.is_dir() {
@@ -2490,6 +2556,7 @@ async fn delete_instance_file(path: String) -> Result<(), String> {
/// Open instance directory in system file explorer
#[tauri::command]
+#[dropout_macros::api]
async fn open_file_explorer(path: String) -> Result<(), String> {
#[cfg(target_os = "windows")]
{
diff --git a/src-tauri/src/utils/api.rs b/src-tauri/src/utils/api.rs
new file mode 100644
index 0000000..0d5a925
--- /dev/null
+++ b/src-tauri/src/utils/api.rs
@@ -0,0 +1,90 @@
+use std::collections::BTreeSet;
+
+#[derive(Debug)]
+pub struct ApiInfo {
+ pub fn_name: &'static str,
+ pub ts_fn_name: &'static str,
+ pub param_names: &'static [&'static str],
+ pub param_defs: &'static [&'static str],
+ pub return_ts_promise: &'static str,
+ pub import_types: &'static [&'static str],
+ pub import_from: Option<&'static str>,
+}
+
+inventory::collect!(ApiInfo);
+
+pub fn export_api_bindings(import_from: &str, export_to: &str) {
+ use std::collections::BTreeMap;
+
+ let api_infos = inventory::iter::<ApiInfo>.into_iter().collect::<Vec<_>>();
+ if api_infos.is_empty() {
+ return;
+ }
+
+ let mut ts_lines = Vec::new();
+ ts_lines.push(r#"import { invoke } from "@tauri-apps/api/core""#.to_string());
+
+ let mut import_types: BTreeMap<&str, BTreeSet<&str>> = BTreeMap::new();
+ let mut ts_funcs = Vec::new();
+ for api_info in api_infos {
+ let api_types = api_info.import_types.iter().cloned().collect::<Vec<_>>();
+ import_types
+ .entry(api_info.import_from.unwrap_or(import_from))
+ .or_insert_with(BTreeSet::new)
+ .extend(api_types.clone());
+ if api_types.contains(&"Vec") {
+ eprintln!("???? from {}", api_info.fn_name)
+ }
+
+ // Determine return generic for invoke: need the raw type (not Promise<...>)
+ let invoke_generic = if api_info.return_ts_promise.starts_with("Promise<")
+ && api_info.return_ts_promise.ends_with('>')
+ {
+ &api_info.return_ts_promise["Promise<".len()..api_info.return_ts_promise.len() - 1]
+ } else {
+ "unknown"
+ };
+ let invoke_line = if api_info.param_names.is_empty() {
+ format!("invoke<{}>(\"{}\")", invoke_generic, api_info.fn_name)
+ } else {
+ format!(
+ "invoke<{}>(\"{}\", {{\n {}\n }})",
+ invoke_generic,
+ api_info.fn_name,
+ api_info.param_names.join(", ")
+ )
+ };
+
+ ts_funcs.push(format!(
+ "export function {}({}): {} {{\n \
+ return {}\n\
+ }}\n",
+ api_info.ts_fn_name,
+ api_info.param_defs.join(", "),
+ api_info.return_ts_promise,
+ invoke_line
+ ))
+ }
+
+ for (import_from, import_types) in import_types {
+ ts_lines.push(format!(
+ "import type {{ {} }} from \"{}\"",
+ import_types.iter().cloned().collect::<Vec<_>>().join(", "),
+ import_from
+ ))
+ }
+ ts_lines.push("".to_string());
+ ts_lines.extend(ts_funcs);
+
+ let ts_content = ts_lines.join("\n");
+ let export_to = std::path::Path::new(export_to);
+ if let Some(parent) = export_to.parent() {
+ std::fs::create_dir_all(parent).expect("Failed to create parent directory");
+ }
+ std::fs::write(export_to, ts_content).unwrap();
+}
+
+#[ctor::dtor]
+fn __dropout_export_api_bindings() {
+ export_api_bindings("@/types", "../packages/ui-new/src/client.ts");
+}
diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs
index c9ac368..709439d 100644
--- a/src-tauri/src/utils/mod.rs
+++ b/src-tauri/src/utils/mod.rs
@@ -1,3 +1,5 @@
+#[cfg(test)]
+pub mod api;
pub mod path;
pub mod zip;