From 1a103de2f1ef75cd73347953cbe27e14606df871 Mon Sep 17 00:00:00 2001 From: 苏向夜 Date: Wed, 18 Feb 2026 15:08:40 +0800 Subject: refactor(client): rewrite macros to generate client --- src-tauri/src/utils/api.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src-tauri/src/utils/api.rs (limited to 'src-tauri/src/utils/api.rs') 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::.into_iter().collect::>(); + 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::>(); + 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::>().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"); +} -- cgit v1.2.3-70-g09d2 From 888f57b6f2ef3b81ba61f4009799f046739ba4dd Mon Sep 17 00:00:00 2001 From: 苏向夜 Date: Tue, 24 Feb 2026 00:24:27 +0800 Subject: feat(macros): sort client api --- crates/macros/src/lib.rs | 6 - packages/ui-new/src/client.ts | 384 +++++++++++++++++++++--------------------- src-tauri/src/utils/api.rs | 7 +- 3 files changed, 198 insertions(+), 199 deletions(-) (limited to 'src-tauri/src/utils/api.rs') diff --git a/crates/macros/src/lib.rs b/crates/macros/src/lib.rs index 21c8bf7..d32ab69 100644 --- a/crates/macros/src/lib.rs +++ b/crates/macros/src/lib.rs @@ -216,12 +216,6 @@ pub fn api(attr: TokenStream, item: TokenStream) -> TokenStream { // Return type let (return_ts_promise, return_imports) = get_return_ts(&input_fn.sig.output); - eprintln!( - "return {} from {} of {}", - return_ts_promise, - return_imports.iter().cloned().collect::>().join(","), - fn_name - ); import_types.extend(return_imports); // Prepare test mod name diff --git a/packages/ui-new/src/client.ts b/packages/ui-new/src/client.ts index 9f4ccf0..572cdd9 100644 --- a/packages/ui-new/src/client.ts +++ b/packages/ui-new/src/client.ts @@ -25,165 +25,207 @@ import type { VersionMetadata, } from "@/types"; -export function setActiveInstance(instanceId: string): Promise { - return invoke("set_active_instance", { - instanceId, +export function assistantChat(messages: Message[]): Promise { + return invoke("assistant_chat", { + messages, }); } -export function refreshAccount(): Promise { - return invoke("refresh_account"); +export function assistantChatStream(messages: Message[]): Promise { + return invoke("assistant_chat_stream", { + messages, + }); } -export function getFabricGameVersions(): Promise { - return invoke("get_fabric_game_versions"); +export function assistantCheckHealth(): Promise { + return invoke("assistant_check_health"); } -export function deleteInstance(instanceId: string): Promise { - return invoke("delete_instance", { +export function cancelJavaDownload(): Promise { + return invoke("cancel_java_download"); +} + +export function checkVersionInstalled( + instanceId: string, + versionId: string, +): Promise { + return invoke("check_version_installed", { instanceId, + versionId, }); } -export function listOllamaModels(endpoint: string): Promise { - return invoke("list_ollama_models", { - endpoint, +export function completeMicrosoftLogin(deviceCode: string): Promise { + return invoke("complete_microsoft_login", { + deviceCode, }); } -export function getForgeVersionsForGame( - gameVersion: string, -): Promise { - return invoke("get_forge_versions_for_game", { - gameVersion, +export function createInstance(name: string): Promise { + return invoke("create_instance", { + name, }); } -export function getVersionMetadata( +export function deleteInstance(instanceId: string): Promise { + return invoke("delete_instance", { + instanceId, + }); +} + +export function deleteInstanceFile(path: string): Promise { + return invoke("delete_instance_file", { + path, + }); +} + +export function deleteVersion( instanceId: string, versionId: string, -): Promise { - return invoke("get_version_metadata", { +): Promise { + return invoke("delete_version", { instanceId, versionId, }); } -export function migrateSharedCaches(): Promise { - return invoke("migrate_shared_caches"); +export function detectAllJavaInstallations(): Promise { + return invoke("detect_all_java_installations"); } -export function getInstance(instanceId: string): Promise { - return invoke("get_instance", { - instanceId, +export function detectJava(): Promise { + return invoke("detect_java"); +} + +export function downloadAdoptiumJava( + majorVersion: number, + imageType: string, + customPath: string | null, +): Promise { + return invoke("download_adoptium_java", { + majorVersion, + imageType, + customPath, }); } -export function getVersions(instanceId: string): Promise { - return invoke("get_versions", { +export function duplicateInstance( + instanceId: string, + newName: string, +): Promise { + return invoke("duplicate_instance", { instanceId, + newName, }); } -export function refreshJavaCatalog(): Promise { - return invoke("refresh_java_catalog"); +export function fetchAdoptiumJava( + majorVersion: number, + imageType: string, +): Promise { + return invoke("fetch_adoptium_java", { + majorVersion, + imageType, + }); +} + +export function fetchAvailableJavaVersions(): Promise { + return invoke("fetch_available_java_versions"); +} + +export function fetchJavaCatalog(): Promise { + return invoke("fetch_java_catalog"); } export function getActiveAccount(): Promise { return invoke("get_active_account"); } -export function getConfigPath(): Promise { - return invoke("get_config_path"); +export function getActiveInstance(): Promise { + return invoke("get_active_instance"); } -export function getForgeGameVersions(): Promise { - return invoke("get_forge_game_versions"); +export function getConfigPath(): Promise { + return invoke("get_config_path"); } -export function getPendingJavaDownloads(): Promise { - return invoke("get_pending_java_downloads"); +export function getFabricGameVersions(): Promise { + return invoke("get_fabric_game_versions"); } -export function listOpenaiModels(): Promise { - return invoke("list_openai_models"); +export function getFabricLoaderVersions(): Promise { + return invoke("get_fabric_loader_versions"); } -export function getRecommendedJava( - requiredMajorVersion: number | null, -): Promise { - return invoke("get_recommended_java", { - requiredMajorVersion, +export function getFabricLoadersForVersion( + gameVersion: string, +): Promise { + return invoke("get_fabric_loaders_for_version", { + gameVersion, }); } -export function fetchAvailableJavaVersions(): Promise { - return invoke("fetch_available_java_versions"); +export function getForgeGameVersions(): Promise { + return invoke("get_forge_game_versions"); } -export function listInstanceDirectory( - instanceId: string, - folder: string, -): Promise { - return invoke("list_instance_directory", { - instanceId, - folder, +export function getForgeVersionsForGame( + gameVersion: string, +): Promise { + return invoke("get_forge_versions_for_game", { + gameVersion, }); } -export function detectJava(): Promise { - return invoke("detect_java"); +export function getGithubReleases(): Promise { + return invoke("get_github_releases"); } -export function openFileExplorer(path: string): Promise { - return invoke("open_file_explorer", { - path, +export function getInstance(instanceId: string): Promise { + return invoke("get_instance", { + instanceId, }); } -export function completeMicrosoftLogin(deviceCode: string): Promise { - return invoke("complete_microsoft_login", { - deviceCode, +export function getPendingJavaDownloads(): Promise { + return invoke("get_pending_java_downloads"); +} + +export function getRecommendedJava( + requiredMajorVersion: number | null, +): Promise { + return invoke("get_recommended_java", { + requiredMajorVersion, }); } -export function startMicrosoftLogin(): Promise { - return invoke("start_microsoft_login"); +export function getSettings(): Promise { + return invoke("get_settings"); } -export function deleteVersion( +export function getVersionJavaVersion( instanceId: string, versionId: string, -): Promise { - return invoke("delete_version", { +): Promise { + return invoke("get_version_java_version", { instanceId, versionId, }); } -export function checkVersionInstalled( +export function getVersionMetadata( instanceId: string, versionId: string, -): Promise { - return invoke("check_version_installed", { +): Promise { + return invoke("get_version_metadata", { instanceId, versionId, }); } -export function uploadToPastebin(content: string): Promise { - return invoke("upload_to_pastebin", { - content, - }); -} - -export function getGithubReleases(): Promise { - return invoke("get_github_releases"); -} - -export function assistantChat(messages: Message[]): Promise { - return invoke("assistant_chat", { - messages, +export function getVersions(instanceId: string): Promise { + return invoke("get_versions", { + instanceId, }); } @@ -199,8 +241,16 @@ export function installFabric( }); } -export function assistantCheckHealth(): Promise { - return invoke("assistant_check_health"); +export function installForge( + instanceId: string, + gameVersion: string, + forgeVersion: string, +): Promise { + return invoke("install_forge", { + instanceId, + gameVersion, + forgeVersion, + }); } export function installVersion( @@ -213,14 +263,6 @@ export function installVersion( }); } -export function listInstalledVersions( - instanceId: string, -): Promise { - return invoke("list_installed_versions", { - instanceId, - }); -} - export function isFabricInstalled( instanceId: string, gameVersion: string, @@ -233,46 +275,44 @@ export function isFabricInstalled( }); } -export function createInstance(name: string): Promise { - return invoke("create_instance", { - name, +export function listInstalledFabricVersions( + instanceId: string, +): Promise { + return invoke("list_installed_fabric_versions", { + instanceId, }); } -export function getVersionJavaVersion( +export function listInstalledVersions( instanceId: string, - versionId: string, -): Promise { - return invoke("get_version_java_version", { +): Promise { + return invoke("list_installed_versions", { instanceId, - versionId, }); } -export function getFabricLoadersForVersion( - gameVersion: string, -): Promise { - return invoke("get_fabric_loaders_for_version", { - gameVersion, +export function listInstanceDirectory( + instanceId: string, + folder: string, +): Promise { + return invoke("list_instance_directory", { + instanceId, + folder, }); } -export function cancelJavaDownload(): Promise { - return invoke("cancel_java_download"); -} - -export function resumeJavaDownloads(): Promise { - return invoke("resume_java_downloads"); +export function listInstances(): Promise { + return invoke("list_instances"); } -export function updateInstance(instance: Instance): Promise { - return invoke("update_instance", { - instance, +export function listOllamaModels(endpoint: string): Promise { + return invoke("list_ollama_models", { + endpoint, }); } -export function getFabricLoaderVersions(): Promise { - return invoke("get_fabric_loader_versions"); +export function listOpenaiModels(): Promise { + return invoke("list_openai_models"); } export function loginOffline(username: string): Promise { @@ -281,76 +321,34 @@ export function loginOffline(username: string): Promise { }); } -export function installForge( - instanceId: string, - gameVersion: string, - forgeVersion: string, -): Promise { - return invoke("install_forge", { - instanceId, - gameVersion, - forgeVersion, - }); -} - -export function detectAllJavaInstallations(): Promise { - return invoke("detect_all_java_installations"); -} - -export function downloadAdoptiumJava( - majorVersion: number, - imageType: string, - customPath: string | null, -): Promise { - return invoke("download_adoptium_java", { - majorVersion, - imageType, - customPath, - }); +export function logout(): Promise { + return invoke("logout"); } -export function startGame( - instanceId: string, - versionId: string, -): Promise { - return invoke("start_game", { - instanceId, - versionId, - }); +export function migrateSharedCaches(): Promise { + return invoke("migrate_shared_caches"); } -export function saveSettings(config: LauncherConfig): Promise { - return invoke("save_settings", { - config, +export function openFileExplorer(path: string): Promise { + return invoke("open_file_explorer", { + path, }); } -export function getSettings(): Promise { - return invoke("get_settings"); -} - -export function duplicateInstance( - instanceId: string, - newName: string, -): Promise { - return invoke("duplicate_instance", { - instanceId, - newName, - }); +export function readRawConfig(): Promise { + return invoke("read_raw_config"); } -export function listInstances(): Promise { - return invoke("list_instances"); +export function refreshAccount(): Promise { + return invoke("refresh_account"); } -export function readRawConfig(): Promise { - return invoke("read_raw_config"); +export function refreshJavaCatalog(): Promise { + return invoke("refresh_java_catalog"); } -export function assistantChatStream(messages: Message[]): Promise { - return invoke("assistant_chat_stream", { - messages, - }); +export function resumeJavaDownloads(): Promise { + return invoke("resume_java_downloads"); } export function saveRawConfig(content: string): Promise { @@ -359,38 +357,40 @@ export function saveRawConfig(content: string): Promise { }); } -export function fetchAdoptiumJava( - majorVersion: number, - imageType: string, -): Promise { - return invoke("fetch_adoptium_java", { - majorVersion, - imageType, +export function saveSettings(config: LauncherConfig): Promise { + return invoke("save_settings", { + config, }); } -export function deleteInstanceFile(path: string): Promise { - return invoke("delete_instance_file", { - path, +export function setActiveInstance(instanceId: string): Promise { + return invoke("set_active_instance", { + instanceId, }); } -export function getActiveInstance(): Promise { - return invoke("get_active_instance"); +export function startGame( + instanceId: string, + versionId: string, +): Promise { + return invoke("start_game", { + instanceId, + versionId, + }); } -export function fetchJavaCatalog(): Promise { - return invoke("fetch_java_catalog"); +export function startMicrosoftLogin(): Promise { + return invoke("start_microsoft_login"); } -export function logout(): Promise { - return invoke("logout"); +export function updateInstance(instance: Instance): Promise { + return invoke("update_instance", { + instance, + }); } -export function listInstalledFabricVersions( - instanceId: string, -): Promise { - return invoke("list_installed_fabric_versions", { - instanceId, +export function uploadToPastebin(content: string): Promise { + return invoke("upload_to_pastebin", { + content, }); } diff --git a/src-tauri/src/utils/api.rs b/src-tauri/src/utils/api.rs index 0d5a925..92e8ab9 100644 --- a/src-tauri/src/utils/api.rs +++ b/src-tauri/src/utils/api.rs @@ -13,13 +13,18 @@ pub struct ApiInfo { inventory::collect!(ApiInfo); +fn sort_api_infos(api_infos: &mut [&ApiInfo]) { + api_infos.sort_by(|a, b| a.fn_name.cmp(b.fn_name)); +} + pub fn export_api_bindings(import_from: &str, export_to: &str) { use std::collections::BTreeMap; - let api_infos = inventory::iter::.into_iter().collect::>(); + let mut api_infos = inventory::iter::.into_iter().collect::>(); if api_infos.is_empty() { return; } + sort_api_infos(&mut api_infos); let mut ts_lines = Vec::new(); ts_lines.push(r#"import { invoke } from "@tauri-apps/api/core""#.to_string()); -- cgit v1.2.3-70-g09d2