CodeVetter · Repo Unpack · Data flow
clash-verge-rev/clash-verge-rev
User input enters through Tauri invoke, the Mihomo plugin's local socket, deep links, or the localhost warp server. Rust turns profiles and verge/clash settings into one runtime YAML via enhance::enhance, validates it by executing the Mihomo sidecar with -t, then applies it to the running core. Live proxy and traffic data flow the other way: the UI polls get_proxy_view and Mihomo HTTP, and the backend pushes verge:// events. Durable files are YAML under the app home. WebDAV credentials are encrypted only while the task-local encryption flag is on.
- src/services/cmds.ts is the typed invoke() boundary. Examples: get_profiles, import_profile, get_proxy_view (rejects schemaVersion other than 1), patch_verge_config, and save_profile_file, which treats ValidationOutcome.status === 'valid' as success.
- Live Mihomo data does not all go through cmds.ts. AppDataProvider uses tauri-plugin-mihomo-api getBaseConfig, getRules, and getRuleProviders, and polls getProxyView every 15 seconds via an SWR wrapper in src/services/query-client.ts.
- Backend events subscribed in src/services/events.ts include verge://refresh-clash-config, verge://refresh-verge-config, verge://refresh-profiles, verge://notice-message, verge://run-state-changed, profile-changed, and profile-update-started/completed.
- In-memory config is Draft<T> from clash-verge-draft: data_arc is the committed snapshot, latest_arc prefers the uncommitted draft, edit_draft clones only when the Arc is shared, and apply commits the draft.
- Config::generate_with_profiles calls enhance::enhance, resolves provider path conflicts, sanitizes tunnels, optionally injects MixedPort::session_fallback, and stores the mapping on the runtime draft as IRuntime { config, dns_override, exists_keys, chain_logs }. generate_file writes that YAML to app_home/clash-verge.yaml with a generated-by header.
- enhance() order is: collect current profile items; process seq rules/proxies/groups; merge GUI clash defaults and port toggles; apply builtin scripts; use_tun; merge dns_config.yaml when DNS settings are enabled; run global merge then global script; run profile merge then profile script; enforce authoritative fields; cleanup proxy groups and sort keys.
- Script enhancers run in Boa. The stock tmpl::ITEM_SCRIPT skips the engine. Other scripts get a 5 second timeout, a 10_000_000 loop-iteration cap, a 10MB JSON input cap, and a console that only calls __verge_log__. Exceptions return the input config unchanged plus an exception log.
- Builtin script src-tauri/src/enhance/builtin/meta_guard.js rewrites config.mode from script to rule. It is applied from the Rust enhancer, not from the webview.
- verge.yaml WebDAV url, username, and password use serialize_encrypted / deserialize_encrypted. AES-256-GCM runs only when ENCRYPTION_ACTIVE is set by with_encryption. help.rs reads and writes YAML inside that scope. The 32-byte key is created with getrandom and stored at app_home/.encryption_key.
- Core config validation shells out to the selected sidecar: app_handle.shell().sidecar(clash_core) with args -t -d <app dir> -f <config path>, timeout 5 seconds. ValidationOutcome is Valid, Invalid, Skipped (exiting or debounced), or Busy.
- A node click calls Mihomo selectNodeForGroup or unfixedProxy, then sync_tray_proxy_selection, then record_selected_node or forget_selected_node. If auto_close_connection is set, connections whose chain includes the previous proxy are closed.
- The embedded warp server binds 127.0.0.1. /commands/visible and /commands/scheme require header x-instance-token. /commands/pac does not: it substitutes %mixed-port% into pac_file_content or DEFAULT_PAC and is fail-closed until PAC_AVAILABLE is set.
- Deep-link import parses clash or clash-verge URLs, takes the raw url= query (percent-decoded at most twice), builds a PrfItem with PrfItem::from_url, appends and saves profiles, refreshes Timer, and calls CoreManager::update_config_forced only when that import becomes the first current profile.