fnva 0.0.53 → 0.0.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,41 +1,58 @@
1
+ <div align="center">
2
+
1
3
  # fnva - Fast Environment Version Alter
2
4
 
3
- [![npm version](https://img.shields.io/npm/v/fnva)](https://www.npmjs.com/package/fnva) [![crates.io](https://img.shields.io/crates/v/fnva)](https://crates.io/crates/fnva) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+ **Fast, cross-platform environment version switcher**
4
6
 
5
- [中文文档](README_zh.md) · [Full English](README_en.md) · [Docs](docs/)
7
+ [中文文档](README_zh.md) · [Architecture](docs/architecture/core-design.md) · [Releases](https://github.com/Protagonistss/fnva/releases)
6
8
 
7
- Cross-platform environment switcher for Java, Claude Code (CC), and LLM setups. Rust single binary with fast startup and zero runtime dependencies.
9
+ [![npm version](https://img.shields.io/npm/v/fnva)](https://www.npmjs.com/package/fnva)
10
+ [![crates.io](https://img.shields.io/crates/v/fnva)](https://crates.io/crates/fnva)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
12
 
9
- ## Install
13
+ <!-- TODO: Add demo.gif here -->
10
14
 
11
- - npm: `npm install -g fnva`
12
- - Cargo: `cargo install fnva`
13
- - Binary: download from [Releases](https://github.com/Protagonistss/fnva/releases) and add to `PATH`.
15
+ </div>
14
16
 
15
- ## Quick start
17
+ fnva is a cross-platform environment switcher for Java, Claude Code (CC), and general LLM setups. Written in Rust, it starts instantly, has zero runtime dependencies, and works via shell snippets without background daemons.
16
18
 
17
- - Init shell (Bash/Zsh): `eval "$(fnva env env --shell bash)"`
18
- PowerShell: `fnva env env --shell powershell | Out-String | Invoke-Expression`
19
- Fish: `fnva env env --shell fish | source`
20
- - Scan Java: `fnva java scan`
21
- - Switch Java for current session: `fnva java use jdk-17` (with shell integration)
22
- - Switch CC profile: `fnva cc use glmcc` (with shell integration)
23
- - New terminals auto-restore your last active environment
19
+ ## Core Features
24
20
 
25
- ## What it does
21
+ - **Fast & Zero Dependencies**: Single static binary.
22
+ - 🔄 **Session & Global Switching**: Per-shell activation and global defaults.
23
+ - 🐚 **Broad Shell Support**: PowerShell, Bash, Zsh, Fish, CMD.
24
+ - 🧠 **Auto-restore**: Opening a new terminal automatically restores your last active environment.
25
+ - ☕ **Smart Java Management**: Scan and dedupe local JDKs.
26
+ - 🤖 **Unified LLM Setup**: Configure LLM API keys in one place.
26
27
 
27
- - Manages multiple Java, CC, and generic LLM configurations.
28
- - Generates shell snippets to activate environments per session or by default.
29
- - **Auto-restore** — new terminals automatically restore the last active CC/Java environment.
30
- - Stores config at `~/.fnva/config.toml` (Windows: `%USERPROFILE%\.fnva\config.toml`).
31
- - Ships as a single binary; no background daemon.
28
+ ## Documentation Navigation
32
29
 
33
- ## Build/test locally
30
+ - [Core Architecture](docs/architecture/core-design.md) (Chinese)
31
+ - [Roadmap](docs/development/roadmap.md) (Chinese)
32
+ - [Contributing](docs/development/contributing.md) (Chinese)
33
+ - [Shell Integration Guide](docs/user-guide/shell-integration.md)
34
34
 
35
+ ## Installation
36
+
37
+ ```bash
38
+ # npm (recommended)
39
+ npm install -g fnva
40
+
41
+ # Cargo
42
+ cargo install fnva
35
43
  ```
36
- cargo fmt && cargo clippy --all-targets -- -D warnings
37
- cargo test
38
- cargo build --release
39
- ```
40
44
 
41
- For platform bundles: `npm run build:platforms`
45
+ Or download from [Releases](https://github.com/Protagonistss/fnva/releases) and add to `PATH`.
46
+
47
+ ## Quick Start
48
+
49
+ - Shell Integration: `eval "$(fnva env env --shell bash)"`
50
+ - Scan Java: `fnva java scan`
51
+ - Switch Java: `fnva java use jdk-17` (with shell integration)
52
+ - Switch CC profile: `fnva cc use glmcc`
53
+
54
+ ## Configuration
55
+ Config is stored at `~/.fnva/config.toml` (Windows: `%USERPROFILE%\.fnva\config.toml`).
56
+
57
+ ## License
58
+ MIT License.
package/bin/fnva.js CHANGED
@@ -101,10 +101,6 @@ function isEnvironmentSwitchCommand(args) {
101
101
  args[1] === 'use';
102
102
  }
103
103
 
104
- function hasDirectExecuteFlag(args) {
105
- return args.includes('--exec') || args.includes('-e');
106
- }
107
-
108
104
  function getShellArg(args) {
109
105
  const idx = args.indexOf('--shell');
110
106
  if (idx !== -1 && idx + 1 < args.length) {
@@ -128,36 +124,6 @@ function hasApplyFlag(args) {
128
124
  return args.includes('--apply');
129
125
  }
130
126
 
131
- function hasAutoExecuteFlag(args) {
132
- return args.includes('--auto');
133
- }
134
-
135
- function removeAutoFlag(args) {
136
- const index = args.indexOf('--auto');
137
- if (index > -1) {
138
- return args.slice(0, index).concat(args.slice(index + 1));
139
- }
140
- return args;
141
- }
142
-
143
- function createTempScriptFile(script, envType, envName) {
144
- try {
145
- const os = require('os');
146
- const path = require('path');
147
-
148
- const prefix = `fnva_${envType}_${envName}`;
149
- const scriptFile = EncodingUtils.createTempPowerShellScript(script, prefix);
150
-
151
- console.log('');
152
- console.log('[INFO] 环境已切换到当前进程。要在新的 PowerShell 窗口中使用此环境,运行:');
153
- console.log(` ${scriptFile}`);
154
- console.log(' 或者: fnva', envType, 'use', envName, '--auto');
155
-
156
- } catch (error) {
157
- console.warn('[WARN] 无法创建临时脚本文件:', error.message);
158
- }
159
- }
160
-
161
127
  function parseEnvironmentScript(scriptContent) {
162
128
  if (!scriptContent || scriptContent.trim() === '') {
163
129
  return {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fnva",
3
- "version": "0.0.53",
3
+ "version": "0.0.56",
4
4
  "description": "跨平台环境切换工具,支持 Java 和 LLM 环境配置",
5
5
  "author": "protagonistss",
6
6
  "license": "MIT",
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  const https = require('https');
9
+ const http = require('http');
9
10
 
10
11
  const REPOS = [
11
12
  { repo: 'temurin8-binaries', major: 8, lts: true },
@@ -89,6 +90,68 @@ function toToml(entry) {
89
90
  return lines.join('\n');
90
91
  }
91
92
 
93
+ // --- Mirror URL verification ---
94
+
95
+ const MIRRORS = [
96
+ { name: 'tsinghua', template: '{base_url}/{major}/jdk/{arch}/{os}/{filename}',
97
+ base_url: 'https://mirrors.tuna.tsinghua.edu.cn/Adoptium' },
98
+ { name: 'aliyun', template: '{base_url}/{major}/{tag}/{filename}',
99
+ base_url: 'https://mirrors.aliyun.com/eclipse/temurin-compliance/temurin' },
100
+ { name: 'github', template: 'https://github.com/adoptium/temurin{major}-binaries/releases/download/{tag}/{filename}',
101
+ base_url: '' },
102
+ ];
103
+
104
+ function renderMirrorUrl(template, base_url, major, tag, filename, os, arch) {
105
+ return template
106
+ .replace('{base_url}', base_url)
107
+ .replace('{major}', String(major))
108
+ .replace('{tag}', tag)
109
+ .replace('{filename}', filename)
110
+ .replace('{os}', os)
111
+ .replace('{arch}', arch);
112
+ }
113
+
114
+ function headCheck(url) {
115
+ return new Promise((resolve) => {
116
+ const mod = url.startsWith('https') ? https : http;
117
+ const req = mod.request(url, { method: 'HEAD', timeout: 10000 }, (res) => {
118
+ resolve(res.statusCode >= 200 && res.statusCode < 400);
119
+ });
120
+ req.on('error', () => resolve(false));
121
+ req.on('timeout', () => { req.destroy(); resolve(false); });
122
+ req.end();
123
+ });
124
+ }
125
+
126
+ async function verifyMirrorUrls(entries) {
127
+ console.log('\n--- Mirror URL verification ---');
128
+ let hasFailure = false;
129
+
130
+ for (const entry of entries) {
131
+ const filename = entry.assets['linux-x64'];
132
+ if (!filename) {
133
+ console.log(` [SKIP] Java ${entry.major}: no linux-x64 asset`);
134
+ continue;
135
+ }
136
+
137
+ let anyOk = false;
138
+ for (const mirror of MIRRORS) {
139
+ const url = renderMirrorUrl(mirror.template, mirror.base_url, entry.major, entry.tag, filename, 'linux', 'x64');
140
+ const ok = await headCheck(url);
141
+ const mark = ok ? 'OK' : 'FAIL';
142
+ console.log(` [${mark}] Java ${entry.major} ${mirror.name}: ${url.substring(0, 80)}...`);
143
+ if (ok) anyOk = true;
144
+ }
145
+
146
+ if (!anyOk) {
147
+ console.log(` [ERROR] Java ${entry.major}: ALL mirrors unreachable!`);
148
+ hasFailure = true;
149
+ }
150
+ }
151
+
152
+ return !hasFailure;
153
+ }
154
+
92
155
  async function main() {
93
156
  console.log('🔍 查询 Adoptium 最新版本...');
94
157
 
@@ -124,6 +187,14 @@ async function main() {
124
187
 
125
188
  fs.writeFileSync(targetPath, toml, 'utf-8');
126
189
  console.log(`\n✅ 已更新 ${targetPath}`);
190
+
191
+ // Verify all mirror URLs are reachable
192
+ const ok = await verifyMirrorUrls(entries);
193
+ if (!ok) {
194
+ console.error('\n❌ Mirror URL verification failed! Check templates in config.rs');
195
+ process.exit(1);
196
+ }
197
+ console.log('\n✅ All mirror URLs verified');
127
198
  }
128
199
 
129
200
  main().catch((e) => {