Skip to content

Export Rust core types to TypeScript with ts-rs and update CI#77

Draft
HsiangNianian wants to merge 41 commits intomainfrom
refactor/migrate-to-react
Draft

Export Rust core types to TypeScript with ts-rs and update CI#77
HsiangNianian wants to merge 41 commits intomainfrom
refactor/migrate-to-react

Conversation

@HsiangNianian
Copy link
Member

@HsiangNianian HsiangNianian commented Jan 21, 2026

Summary by Sourcery

Export backend data structures to TypeScript for the new React-based UI and update CI to build additional targets.

New Features:

  • Generate TypeScript definitions for core backend structs and enums used by the UI.
  • Now use our own Azure app(DropOut) to finish the authorize process.

Enhancements:

  • Annotate existing Rust models with ts-rs metadata to control exported TypeScript shapes, including tagged enums and opaque JSON fields.

Build:

  • Add ts-rs as a dependency for generating TypeScript bindings from Rust types.

CI:

  • Extend the Semifold CI workflow to run on the dev branch and build additional Linux musl and Windows GNU targets using cross where needed.

Copilot AI review requested due to automatic review settings January 21, 2026 06:13
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 21, 2026

Reviewer's Guide

Adds TypeScript type generation for Tauri backend structs/enums using ts-rs, updates CI to build on additional targets (musl & Windows GNU) with cross support, switches the Microsoft auth client ID, and tweaks a few serialization details for TS/serde interoperability.

Class diagram for auth and account TypeScript-backed models

classDiagram
    class Account {
    }
    <<enumeration>> Account
    Account : Offline(OfflineAccount)
    Account : Microsoft(MicrosoftAccount)

    class OfflineAccount {
        String username
        String uuid
    }

    class MicrosoftAccount {
        String username
        String uuid
        String access_token
        String refresh_token
        u64 expires_at
    }

    class DeviceCodeResponse {
        String user_code
        String device_code
        String verification_uri
        u64 expires_in
        u64 interval
        Option~String~ message
    }

    class TokenResponse {
        String access_token
        Option~String~ refresh_token
        Option~u64~ expires_in
        String token_type
        Option~String~ scope
    }

    class MinecraftAuthResponse {
        String username
        String access_token
        String token_type
        u64 expires_in
    }

    class MinecraftProfile {
        String id
        String name
    }

    Account *-- OfflineAccount
    Account *-- MicrosoftAccount
Loading

Class diagram for download and Java management models exported to TypeScript

classDiagram
    class DownloadTask {
        String url
        PathBuf path
        u64 total_size
        bool resumable
        u32 segments
    }

    class DownloadMetadata {
        String url
        String file_name
        u64 total_size
        u64 downloaded
        u32 segments
        bool resumable
    }

    class DownloadSegment {
        u64 start
        u64 end
        u64 downloaded
        u32 index
    }

    class JavaDownloadProgress {
        String file_name
        u64 downloaded_bytes
        u64 total_bytes
        f32 progress
        bool done
    }

    class PendingJavaDownload {
        u32 major_version
        String image_type
        String jvm_impl
        String os
        String arch
    }

    class DownloadQueue {
        Vec~PendingJavaDownload~ pending_downloads
    }

    class ProgressEvent {
        String file
        u64 downloaded
        u64 total
        f32 progress
        bool done
    }

    class JavaInstallation {
        String path
        String version
        String vendor
        String image_type
    }

    class ImageType {
    }
    <<enumeration>> ImageType
    ImageType : Jre
    ImageType : Jdk

    class JavaReleaseInfo {
        u32 major_version
        String image_type
        String jvm_impl
        String os
        String arch
        String version
        String release_name
        String download_url
        String checksum
        u64 size
        bool lts
    }

    class JavaCatalog {
        Vec~JavaReleaseInfo~ releases
        Vec~u32~ available_major_versions
        Vec~String~ available_image_types
        Vec~String~ available_jvm_impls
    }

    class JavaDownloadInfo {
        String version
        String release_name
        String download_url
        String checksum
        u64 size
    }

    DownloadQueue *-- PendingJavaDownload
    JavaCatalog *-- JavaReleaseInfo
Loading

File-Level Changes

Change Details Files
Generate TypeScript definitions from Rust backend models using ts-rs for the new React UI
  • Add ts-rs as a dependency in Cargo.toml
  • Import ts_rs::TS in core modules that define API-facing structs/enums
  • Derive TS for many existing data structs/enums (game versions, Fabric/Forge metadata, downloader/auth/java/config/instance/assistant types, etc.)
  • Configure #[ts(export, export_to = ...)] paths to write generated .ts files into packages/ui/src/types/generated
  • Override some TS field types (e.g. serde_json::Value mapped to Record<string, unknown>, PathBuf mapped to string, enum naming/tagging tweaks) to better match frontend expectations
src-tauri/Cargo.toml
src-tauri/src/core/game_version.rs
src-tauri/src/core/fabric.rs
src-tauri/src/core/downloader.rs
src-tauri/src/core/auth.rs
src-tauri/src/main.rs
src-tauri/src/core/java.rs
src-tauri/src/core/assistant.rs
src-tauri/src/core/config.rs
src-tauri/src/core/instance.rs
src-tauri/src/core/forge.rs
src-tauri/src/core/manifest.rs
Adjust authentication configuration and exported auth-related types
  • Change CLIENT_ID constant back to the app’s own Azure AD client ID and comment out the previous ATLauncher client ID
  • Export DeviceCodeResponse, TokenResponse, MinecraftProfile and account-related types via ts-rs for frontend consumption
src-tauri/src/core/auth.rs
Expose additional backend view models for UI via ts-rs
  • Export VersionMetadata, InstalledVersion, GithubRelease, PastebinResponse, MigrationResult, FileInfo, Java-related info structs, and other UI view models used by Tauri commands
src-tauri/src/main.rs
src-tauri/src/core/java.rs
Expand CI matrix to support musl and Windows GNU builds using cross where needed
  • Trigger Semifold CI on both main and dev branches
  • Re-enable Linux x86_64 musl build and configure it to use cross
  • Re-enable Windows x86_64 GNU build with additional rustflags for ws2_32 linking
  • Plumb optional matrix fields (use-cross, rustflags) into the tauri-action step, including switching between cargo and cross based on the matrix
  • Install cross conditionally when required by the matrix
.github/workflows/semifold-ci.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@HsiangNianian
Copy link
Member Author

@SourceryAI title

@github-actions
Copy link
Contributor

github-actions bot commented Jan 21, 2026

Workspace change through: c46d6c5

2 changesets found

Planned changes to release
Package Bump Level Current Version Next Version
dropout patch 0.2.0-alpha.1 0.2.0-alpha.2
dropout-macros patch 0.1.0 0.1.0-alpha.0

@HsiangNianian HsiangNianian requested review from fu050409 and removed request for Copilot January 21, 2026 06:13
@sourcery-ai sourcery-ai bot changed the title Refactor/migrate to react Export Rust core types to TypeScript with ts-rs and update CI Jan 21, 2026
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • The ts_rs usage is very repetitive, especially the long export_to paths; consider centralizing the base output directory (e.g., via a macro, helper attribute, or build script) so new types and path changes are less error‑prone.
  • Several fields containing arbitrary JSON are exported as Record<string, unknown> (e.g., natives, features, classifiers, Arguments fields); if the frontend relies on particular keys or shapes, it may be worth tightening these TypeScript types to catch UI-side misuse earlier.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `ts_rs` usage is very repetitive, especially the long `export_to` paths; consider centralizing the base output directory (e.g., via a macro, helper attribute, or build script) so new types and path changes are less error‑prone.
- Several fields containing arbitrary JSON are exported as `Record<string, unknown>` (e.g., `natives`, `features`, `classifiers`, `Arguments` fields); if the frontend relies on particular keys or shapes, it may be worth tightening these TypeScript types to catch UI-side misuse earlier.

## Individual Comments

### Comment 1
<location> `src-tauri/src/core/game_version.rs:6-13` </location>
<code_context>

 /// Represents a Fabric loader version from the Meta API.
-#[derive(Debug, Deserialize, Serialize, Clone)]
+#[derive(Debug, Deserialize, Serialize, Clone, TS)]
+#[ts(
+    export,
</code_context>

<issue_to_address>
**issue (bug_risk):** Serde-renamed fields (e.g. `majorVersion`) will be mismatched in generated TS without `ts` renames or `serde-compat`.

For types like `JavaVersion`, `serde(rename = "majorVersion")` changes the JSON field, but `ts-rs` will still emit `major_version` unless configured otherwise. This makes the generated TS types disagree with the actual API. Please either:

1) Enable `ts-rs`’s `serde-compat` feature so serde renames are mirrored automatically, or
2) Add `#[ts(rename = "majorVersion")]` (and similar `ts` renames wherever `serde(rename = ...)` is used).

Otherwise the frontend will receive `majorVersion` while the TS types expect `major_version`.
</issue_to_address>

### Comment 2
<location> `src-tauri/src/main.rs:1753-1760` </location>
<code_context>

 /// Version metadata for display in the UI
-#[derive(serde::Serialize)]
+#[derive(serde::Serialize, TS)]
+#[ts(
+    export,
+    export_to = "../../packages/ui/src/types/generated/VersionMetadata.ts"
+)]
 struct VersionMetadata {
     id: String,
     #[serde(rename = "javaVersion")]
</code_context>

<issue_to_address>
**issue (bug_risk):** Generated TS for `VersionMetadata`/`InstalledVersion` fields won’t respect serde `rename`, causing type/JSON divergence.

In `VersionMetadata` and `InstalledVersion`, fields using `#[serde(rename = ...)]` (e.g. `javaVersion`, `type`) will still be emitted by `ts-rs` as `java_version`/`r#type` unless configured. That means the generated TS types won’t match the actual JSON shape the frontend receives.

Please either enable `ts-rs`’s `serde-compat` feature globally, or add explicit `#[ts(rename = "...")]` on the renamed fields so the TS definitions align with the serialized JSON.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copilot AI review requested due to automatic review settings January 21, 2026 06:40
@HsiangNianian HsiangNianian marked this pull request as draft January 21, 2026 06:41
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds TypeScript type generation from Rust backend types using the ts-rs library. The changes enable automatic generation of TypeScript definitions for all data structures used in communication between the Rust backend and the frontend UI, ensuring type safety across the Rust-TypeScript boundary.

Changes:

  • Added ts-rs 11.1.0 dependency to Cargo.toml
  • Annotated 40+ core Rust structs and enums with #[derive(TS)] and export metadata
  • Configured TypeScript output paths to packages/ui/src/types/generated/
  • Added proper type overrides for complex types (PathBuf → string, serde_json::Value → Record<string, unknown>)

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src-tauri/Cargo.toml Added ts-rs dependency for TypeScript type generation
src-tauri/src/main.rs Added TS import and annotations for UI-facing types (VersionMetadata, InstalledVersion, GithubRelease, PastebinResponse, MigrationResult, FileInfo)
src-tauri/src/core/auth.rs Annotated authentication types with TS exports including tagged Account enum; includes unrelated CLIENT_ID change
src-tauri/src/core/config.rs Exported configuration types (LauncherConfig, AssistantConfig, FeatureFlags)
src-tauri/src/core/downloader.rs Exported download-related types with progress tracking structures
src-tauri/src/core/fabric.rs Exported Fabric loader types including loader versions, libraries, and main class enum
src-tauri/src/core/forge.rs Exported Forge types with proper PathBuf→string type override
src-tauri/src/core/game_version.rs Exported comprehensive game version types with Record<string, unknown> overrides for serde_json::Value fields
src-tauri/src/core/instance.rs Exported instance/profile configuration types
src-tauri/src/core/java.rs Exported Java installation and catalog types with ImageType enum
src-tauri/src/core/manifest.rs Exported Mojang version manifest types
src-tauri/src/core/assistant.rs Exported AI assistant message and model types

NtskwK and others added 11 commits January 29, 2026 02:54
- Centralize strip_unc_prefix into java/mod.rs to eliminate duplication across detection.rs and validation.rs
- Remove unused JAVA_CHECK_TIMEOUT constant from validation.rs
- Implement actual timeout mechanism in run_which_command_with_timeout() using try_wait() loop
- Parallelize Adoptium API requests for better catalog fetch performance

Fixes:
- Multiple strip_unc_prefix implementations consolidated
- Timeout constant now properly enforced in which/where command execution
- Catalog fetching now uses concurrent tokio::spawn tasks instead of sequential await

Reviewed-by: Claude Sonnet 4.5
- Add #[allow(dead_code)] attributes to utility functions
- Improve 64-bit detection with case-insensitive check
- Support aarch64 architecture in bitness detection
- Add TODO for future vendor expansion

Reviewed-by: Claude Sonnet 4.5
Replace potentially panicking unwrap() call with expect() that includes a descriptive error message to aid debugging if the edge case occurs.

Reviewed-by: Claude Sonnet 4.5
…r handling

- Extract version compatibility check into shared validation function
- Remove duplicated version checking code across multiple modules
- Simplify Java detection timeout logic in detection.rs
- Expand vendor detection to support more JDK distributions (Dragonwell, Kona, Semeru, BiSheng, etc.)
- Refactor start_game to use priority-based Java resolution
- Improve error handling in Adoptium provider task collection

Reviewed-by: Claude Sonnet 4.5
- Added support for detecting Java installations from SDKMAN! in `find_sdkman_java`.
- Improved `run_which_command_with_timeout` to handle command timeouts gracefully.
- Introduced a unified `JavaError` enum for consistent error handling across Java operations.
- Updated functions to return `Result` types instead of `Option` for better error reporting.
- Enhanced `load_cached_catalog` and `save_catalog_cache` to use `JavaError`.
- Refactored `fetch_java_catalog`, `fetch_java_release`, and `fetch_available_versions` to return `JavaError`.
- Improved validation functions to return detailed errors when checking Java installations.
- Added tests for version parsing and compatibility checks.
- Updated `resolve_java_for_launch` to handle instance-specific and global Java paths.
…eanup

- Add CACHE_VERSION constant for cache format compatibility tracking
- Add MAX_CACHE_SIZE_BYTES limit (10 MB) to prevent unbounded cache growth
- Add cache_version field to JavaCatalog struct with default value
- Implement cache version validation in load_cached_catalog()
- Implement cache size enforcement in save_catalog_cache()
- Add cleanup_expired_caches() for background cache cleanup
- Add enforce_cache_size_limit() to validate cache file sizes
- Add is_cache_version_compatible() helper function
- Automatically clean up expired caches on load and clear operations
- Validate cache version before using cached data

Fixes:
- Cache expiration without automatic cleanup (now cleaned on load)
- Missing cache version control (now validates format compatibility)
- Unbounded cache size growth (now limited to 10 MB)

Reviewed-by: Claude 3.5 Sonnet
- Extract JavaError to dedicated error.rs module
- Add serde defaults for JavaInstallation optional fields
- Replace unwrap() with proper error propagation
- Add detailed logging for Java resolution priority chain
- Improve error mapping in validation (NotFound vs VerificationFailed)

Reviewed-by: Claude Sonnet 4.5
- Export JavaError from java module
- Fix type mismatches in Adoptium provider methods
- Add type annotations for reqwest json() calls
- Remove non-existent cache_version field from JavaCatalog
- Fix resolve_java_for_launch call signature (remove extra window param)
- Add error conversion to String for Tauri commands
- Fix import for save_catalog_cache in adoptium.rs

Reviewed-by: Claude Sonnet 4.5
BegoniaHe added a commit to BegoniaHe/DropOut that referenced this pull request Jan 29, 2026
Integrate Java runtime refactoring changes:
- Modular Java detection and management system
- Adoptium Java provider with automatic download
- Instance-level Java path overrides
- Priority-based Java resolution
- Enhanced error handling with JavaError type
- Cache management with versioning

This merge combines the ts-rs TypeScript bindings work from PR HydroRoll-Team#77
with the comprehensive Java runtime improvements from PR HydroRoll-Team#82.
…ogic

- Add scan_java_dir() helper to filter symlinks and scan directories
- Implement find_mise_java() for ~/.local/share/mise/installs/java/
- Refactor find_sdkman_java() to scan candidates dir instead of 'current'
- Fix import paths to use absolute crate::core::java:: paths
- Add mise detection to Linux and macOS candidates

Reviewed-by: Claude Sonnet 4.5
- Regenerate ts-rs bindings with single-line type definitions
- Add new bindings: account_storage.ts, java module types
- Update all existing binding files to compact format
- Add generated types for old UI package

Reviewed-by: Claude Sonnet 4.5
BegoniaHe and others added 2 commits February 5, 2026 00:52
)

# 描述

此 PR 为 Java 检测模块添加了 mise 版本管理器支持,并重构了 SDKMAN 检测逻辑,使其更加健壮。同时更新了
TypeScript 类型绑定的格式。

## 更改类型

- [ ] Bug 修复(修复问题的非破坏性更改)
- [x] 新功能(添加功能的非破坏性更改)
- [ ] 破坏性更改(会导致现有功能无法正常工作的修复或功能)
- [ ] 文档更新
- [ ] UI/UX 改进
- [ ] 性能优化
- [x] 代码重构(无功能性更改)
- [ ] 配置更改
- [ ] 测试添加或更新

## LLM 生成代码声明

- [x] 此 PR 包含 LLM 生成的代码,我**提供**质量担保
- [ ] 此 PR 包含 LLM 生成的代码,我**不提供**质量担保
- [ ] 此 PR 不包含 LLM 生成的代码

**模型**: Claude Sonnet 4.5

## 相关 Issue

相关 #(如有)

## 更改内容

### 后端 (Rust)

#### Java 检测模块重构

1. **新增 mise 版本管理器支持**
   - 添加 `find_mise_java()` 函数扫描 `~/.local/share/mise/installs/java/`
   - 在 Linux 和 macOS 平台的候选列表中集成 mise 检测

2. **重构 SDKMAN 检测逻辑**
   - 将 `find_sdkman_java()` 从检查 `current` 符号链接改为扫描整个 candidates 目录
   - 避免符号链接导致的重复检测问题

3. **添加通用扫描辅助函数**
   - 实现 `scan_java_dir<F>()` 泛型函数,支持自定义过滤条件
   - 自动过滤符号链接,只返回真实的目录安装
   - 为 mise 和 SDKMAN 提供统一的扫描逻辑

4. **修复模块导入路径**
   - 将相对导入 `super::` 改为绝对导入 `crate::core::java::`
   - 提高代码可维护性和清晰度

5. **改进文档注释**
   - 为新函数添加详细的 Rustdoc 注释
   - 说明参数、返回值和功能

### 前端 (React)

- 无前端更改

### 配置

- 重新生成 TypeScript 类型绑定(ts-rs),采用更紧凑的单行格式
- 新增类型:`account_storage.ts`、`java/*` 模块类型
- 更新所有现有绑定文件的格式

## 测试

### 测试环境

- **操作系统**:Windows 11
- **DropOut 版本**:0.1.24
- **测试的 Minecraft 版本**:N/A(Java 检测功能)
- **Mod 加载器**:N/A

### 测试用例

- [x] 已在 Windows 上测试(编译通过)
- [ ] 已在 macOS 上测试
- [ ] 已在 Linux 上测试
- [ ] 已测试原版 Minecraft
- [ ] 已测试 Fabric
- [ ] 已测试 Forge
- [ ] 已测试游戏启动
- [ ] 已测试登录流程
- [x] 已测试 Java 检测/下载

### 测试步骤

1. 运行 `cargo tauri dev` 确保编译通过
2. 运行 `cargo check` 和 `cargo clippy` 确保无警告
3. Pre-commit hooks 全部通过(fmt, check, clippy)

**注意**:此 PR 主要是代码重构和新增功能,建议在具有 mise/SDKMAN 环境的 Linux/macOS 系统上进行实际功能测试。

## 检查清单

### 代码质量

- [x] 我的代码遵循项目的代码风格指南
- [x] 我已对自己的代码进行了自审
- [x] 我已对难以理解的区域添加了注释
- [x] 我的更改没有产生新的警告或错误

### 测试验证

- [x] 我已在本地测试了我的更改
- [ ] 我已添加测试来证明我的修复有效或功能正常工作
- [ ] 新的和现有的单元测试在本地通过
- [x] 我至少在一个目标平台上进行了测试(Windows 编译测试)

### 文档更新

- [x] 我已相应地更新了文档(代码注释)
- [ ] 如有需要,我已更新 README
- [x] 我已在必要处添加/更新代码注释

### 依赖项

- [x] 我已检查没有添加不必要的依赖项
- [x] 所有新依赖项都已正确记录
- [x] `Cargo.lock` 和/或 `pnpm-lock.yaml` 已更新(如果依赖项有变化)

## 截图 / 视频

N/A(后端功能,无 UI 变更)

## 附加说明

### 技术细节

**为什么添加 mise 支持?**
mise (前身 rtx) 是一个现代的版本管理工具,越来越多的开发者使用它来管理 Java 等运行时。添加此支持可以提高启动器的兼容性。

**符号链接过滤的重要性**
版本管理器(mise/SDKMAN)通常会创建符号链接作为版本别名(如 `21`、`lts`、`current`),过滤这些链接可以:
- 避免重复检测同一个 Java 安装
- 减少检测开销
- 提供更清晰的检测结果

**代码重构的影响**
- 导入路径的更改不影响功能,仅提高代码组织性
- TypeScript 绑定的格式更改由 ts-rs 自动生成,不影响类型定义的正确性

### 后续工作建议

- 在 CI 中添加 Linux/macOS 环境的 Java 检测集成测试
- 考虑为其他版本管理器(如 jenv、jabba)添加支持
- 优化检测性能(可能需要并行扫描或缓存机制)

## 破坏性更改说明

无破坏性更改。此 PR 完全向后兼容。

---

**维护者专用:**

- [ ] 代码审查已完成
- [ ] CI 检查通过
- [ ] 准备合并

---

**提交记录:**
- 50de089 feat(java): add mise version manager support and refactor
detection logic
- c075dd8 chore(types): regenerate typescript bindings with compact
formatting

**Reviewed-by**: Claude Sonnet 4.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: high HighPriority Stuff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants