Platform Redirection Guide
Overview
vx uses a platform-agnostic API with automatic platform-specific storage. This allows:
- Unified API: Access tools using
<provider>/<version>/paths - Platform-specific Storage: Files stored in
<provider>/<version>/<platform>/directories - Automatic Redirection: PathManager transparently redirects to current platform
- Offline Bundle Support: Single bundle can contain all platforms
Directory Structure
~/.vx/store/
├── node/
│ └── 20.0.0/ # Unified version directory (API)
│ ├── windows-x64/ # Platform-specific (storage)
│ ├── darwin-x64/
│ └── linux-x64/
├── python/
│ └── 3.9.21/
│ ├── windows-x64/
│ └── linux-x64/
└── uv/
└── 0.5.0/
├── windows-x64/
└── linux-x64/API Changes
PathManager
New methods added to vx_paths::PathManager:
rust
/// Get platform directory name for current platform
/// Returns: "windows-x64", "darwin-arm64", "linux-x64", etc.
pub fn platform_dir_name(&self) -> String
/// Get actual platform-specific store directory
/// Returns: ~/.vx/store/<runtime>/<version>/<platform>
pub fn platform_store_dir(&self, runtime_name: &str, version: &str) -> PathBuf
/// Get actual executable path in platform-specific directory
/// Returns: ~/.vx/store/<runtime>/<version>/<platform>/bin/<runtime>.exe
pub fn platform_executable_path(&self, runtime_name: &str, version: &str) -> PathBuf
/// Check if a runtime version is installed (checks platform-specific dir)
pub fn is_version_in_store(&self, runtime_name: &str, version: &str) -> bool
/// List all installed versions (checks platform-specific dirs)
pub fn list_store_versions(&self, runtime_name: &str) -> Result<Vec<String>>PathResolver
All store lookup methods now automatically use platform-specific directories:
rust
// These all use platform_store_dir internally:
pub fn find_tool(&self, tool_name: &str) -> Result<Option<ToolLocation>>
pub fn find_in_store(&self, tool_name: &str) -> Result<Option<ToolLocation>>
pub fn find_in_store_with_exe(
&self,
tool_name: &str,
exe_name: &str,
) -> Result<Option<ToolLocation>>
pub fn find_all_in_store(&self, tool_name: &str) -> Result<Vec<ToolLocation>>
pub fn find_all_in_store_with_exe(
&self,
tool_name: &str,
exe_name: &str,
) -> Result<Vec<ToolLocation>>
pub fn find_tool_version(&self, tool_name: &str, version: &str) -> Option<ToolLocation>
pub fn find_tool_version_with_executable(
&self,
tool_name: &str,
version: &str,
exe_name: &str,
) -> Option<ToolLocation>>Runtime Installation
When installing a runtime, files are stored in platform-specific directory:
rust
// In Runtime::install():
let base_install_path = ctx.paths.version_store_dir(store_name, version);
let install_path = base_install_path.join(platform.as_str());
// Files extracted to: ~/.vx/store/<name>/<version>/<platform>/Offline Bundle Creation
Create offline bundles that work across all platforms:
bash
# Bundle structure
vx-bundle/
└── store/
└── node/
└── 20.0.0/
├── windows-x64/ # All platforms in one bundle
├── darwin-x64/
└── linux-x64/When extracting the bundle, vx automatically selects the correct platform directory for the current system.
Migration Guide
For Runtime Implementors
If you implement custom runtimes, ensure installation uses platform directories:
rust
async fn install(&self, version: &str, ctx: &RuntimeContext) -> Result<InstallResult> {
let store_name = self.store_name();
let platform = Platform::current();
// Use platform-specific directory
let base_install_path = ctx.paths.version_store_dir(store_name, version);
let install_path = base_install_path.join(platform.as_str());
// Download and extract to install_path
ctx.installer.download_and_extract(&url, &install_path).await?;
Ok(InstallResult::success(install_path, exe_path, version.to_string()))
}For Path Usage
When looking up installed tools, use platform-specific directories:
rust
let resolver = PathResolver::new()?;
// These automatically use platform-specific directories
let tool = resolver.find_tool("node")?;
let latest = resolver.find_latest_tool("node")?;
let versions = resolver.list_store_versions("node")?;
// Find specific version (uses platform directory)
let node_20 = resolver.find_tool_version("node", "20.0.0")?;Benefits
- Cross-Platform Compatibility: Same bundle works on Windows, macOS, Linux
- Disk Efficiency: Multiple platforms can share same bundle
- Transparent API: Users don't need to know platform details
- Easy Distribution: Single bundle supports all platforms
- Future-Proof: Easy to add new platform support
Implementation Details
Platform Detection
vx_paths includes a lightweight platform detector:
rust
pub struct CurrentPlatform {
pub os: &'static str, // "windows", "darwin", "linux", etc.
pub arch: &'static str, // "x64", "arm64", etc.
}
impl CurrentPlatform {
pub fn current() -> Self { /* compile-time detection */ }
pub fn as_str(&self) -> String { /* "windows-x64", etc. */ }
}Path Resolution
- Lookup: Request
<provider>/<version>/ - Redirect: Check
<provider>/<version>/<platform>/ - Fallback: Return None if not found
This happens automatically in PathResolver methods.
Testing
Test platform-specific paths:
rust
#[test]
fn test_platform_redirection() {
let manager = PathManager::new()?;
let platform_dir = manager.platform_store_dir("node", "20.0.0");
assert!(platform_dir.ends_with("node/20.0.0/windows-x64"));
let versions = manager.list_store_versions("node")?;
// Only versions with current platform subdirectory are listed
}