sdkvm 1.0.0 → 1.0.1

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
@@ -10,24 +10,24 @@
10
10
  [![node](https://img.shields.io/badge/node-%3E%3D18.15-green)](./package.json)
11
11
  [![platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-blue)](#系统要求)
12
12
 
13
- 像 [nvm](https://github.com/nvm-sh/nvm) 管理 Node.js 一样管理 **Java JDK**、**Go 工具链** 与 **Flutter SDK**。
13
+ 中文 | [English](./README.en.md)
14
14
 
15
- </div>
15
+ 管理 **Java JDK**、**Go 工具链**、**Flutter SDK** 与 **Node.js 运行时**。
16
16
 
17
- ---
17
+ </div>
18
18
 
19
19
  ## 目录
20
20
 
21
21
  - [简介](#简介)
22
- - [从 easy-jvm 升级](#从-easy-jvm-升级)
23
22
  - [系统要求](#系统要求)
24
23
  - [安装](#安装)
24
+ - [升级](#升级)
25
25
  - [快速开始](#快速开始)
26
26
  - [命令参考](#命令参考)
27
27
  - [版本语法](#版本语法)
28
28
  - [工作原理](#工作原理)
29
29
  - [配置](#配置)
30
- - [镜像加速(国内用户)](#镜像加速国内用户)
30
+ - [镜像与 npm 源](#镜像与-npm-源)
31
31
  - [安全性](#安全性)
32
32
  - [常见问题](#常见问题)
33
33
  - [卸载](#卸载)
@@ -36,118 +36,174 @@
36
36
 
37
37
  ## 简介
38
38
 
39
- `sdkvm` 是一个用 Node.js 编写的命令行工具,提供多种语言 SDK 的**安装、切换、卸载**能力:
39
+ `sdkvm` 用 Node.js 编写,负责多种语言 SDK 的安装、切换和卸载。
40
+
41
+ | SDK | 来源 | 说明 |
42
+ |---|---|---|
43
+ | Java | [Temurin](https://adoptium.net/)、[Zulu](https://www.azul.com/downloads/)、[Corretto](https://aws.amazon.com/corretto/) | `lts` 当前为 8 / 11 / 17 / 21 / 25 |
44
+ | Go | [go.dev](https://go.dev/dl/) | 全历史稳定版 |
45
+ | Flutter | 官方发布清单 | stable / beta;macOS 双架构,Linux / Windows 仅 x64 |
46
+ | Node.js | [nodejs.org/dist](https://nodejs.org/dist) | `lts`(当前 24 Krypton)/ `latest` / 按 major 线;npm 随版本切换 |
47
+
48
+ 行为约定:
49
+
50
+ - 各 SDK 目录隔离,`JAVA_HOME`、`GO_HOME`、`FLUTTER_HOME`、`NODE_HOME` 互不覆盖。
51
+ - `use` 只改一个符号链接(Windows 为 junction),不搬移已安装的文件。
52
+ - 下载地址由官方 API 解析。Go、Flutter、Node.js 强制校验 SHA-256;Java 各源尽力校验。
53
+ - Temurin、Go、Flutter、Node.js 可配置镜像。校验和仍取自官方清单。
54
+ - 新增语言只需实现一个厂商模块,见[开发](#开发)。
40
55
 
41
- - **Java**:内置 [Adoptium Temurin](https://adoptium.net/)、[Azul Zulu](https://www.azul.com/downloads/)、[Amazon Corretto](https://aws.amazon.com/corretto/) 三个主流发行版,支持 `lts` 语义(当前 LTS:8 / 11 / 17 / 21 / 25)
42
- - **Go**:官方 [go.dev](https://go.dev/dl/) 源,全历史稳定版可装
43
- - **Flutter**:官方发布清单(stable / beta 通道),macOS 双架构、Linux / Windows x64
44
- - **多平台**:macOS(Apple Silicon / Intel)、Linux、Windows 10+
45
- - **开箱即用**:仅依赖 Node.js 与系统自带的 tar / PowerShell,各 SDK 完全隔离,`JAVA_HOME` / `GOROOT` / `FLUTTER_ROOT` 并存互不干扰
46
- - **秒级切换**:`use` 只更新一个符号链接(Windows 为 junction),不搬移文件、不改全局环境
47
- - **官方源直连**:下载地址一律经官方 API 解析;Go 与 Flutter 的官方清单内联 SHA-256,**强制校验**,其余源尽力校验
48
- - **镜像支持**:Temurin、Go、Flutter 均可配置国内镜像加速下载(校验和仍取自官方,镜像文件被交叉验证)
49
- - **可扩展**:SDK 类型抽象(`src/sdk/`)之上新增语言只需实现一个厂商模块(见[开发](#开发))
56
+ ## 系统要求
57
+
58
+ | 依赖 | 版本 | 说明 |
59
+ |---|---|---|
60
+ | Node.js | >= 18.15 | npm 安装需要本机 Node。脚本安装自带隔离运行时,不要求预先安装 |
61
+ | 操作系统 | — | macOS(Apple Silicon / Intel)、主流 Linux、Windows 10+ |
62
+ | 解压工具 | 系统自带 | macOS / Linux 用 `tar`;Windows 用 bsdtar,缺失时回退 PowerShell `Expand-Archive` |
63
+
64
+ 平台限制:
50
65
 
51
- ## 从 easy-jvm 升级
66
+ - Linux 解压 Flutter(`.tar.xz`)需要 `xz`(`xz-utils`)。主流发行版默认自带。
67
+ - Flutter 官方在 Linux / Windows 只发布 x64 归档。ARM Linux 与 ARM Windows 无法安装。macOS 两种架构都支持。
68
+ - `flutter` 首次运行会构建内部 cache,耗时较久属于正常现象。
52
69
 
53
- `sdkvm` 是 `easy-jvm` 的更名升级版(原工具只管理 JDK)。已装用户:
70
+ ## 安装
71
+
72
+ ### npm、pnpm、yarn、bun
73
+
74
+ 本机需要 Node.js >= 18.15。四条命令都从 npm registry 安装:
54
75
 
55
76
  ```sh
56
- npm uninstall -g easy-jvm # 先卸载旧包,避免残留的 jvm 命令重建空 ~/.jvm
57
77
  npm install -g sdkvm
78
+ pnpm add -g sdkvm
79
+ yarn global add sdkvm
80
+ bun add -g sdkvm
58
81
  ```
59
82
 
60
- 首次运行任意命令时,`~/.jvm/` 会**自动整体迁移**为 `~/.sdkvm/`:
83
+ 装好后 CLI 使用 `PATH` 上的 `node`。若之后切到 18.15 以前的 Node,CLI 会无法启动,切回较新版本即可。
61
84
 
62
- - 迁移是一次**原子目录改名**(同卷 `rename`,无中间失败窗口),已装 JDK 原样保留,无需重装
63
- - 随后自动改写:`current` 链接(更名为 `current-java`,绝对目标同步指向新路径)、Windows 注册表 `JAVA_HOME` 字面值、shell 配置文件中的旧 `# >>> jvm init >>>` 标记块
64
- - 幂等:迁移过一次后再运行不会重复动作;`~/.sdkvm/` 已存在时不自动合并,仅提示手动处理
65
- - 旧的 `JVM_HOME` / `JVM_MIRROR` / `JVM_QUIET` 环境变量**永久作为别名**继续识别
85
+ ### 安装脚本
66
86
 
67
- ## 系统要求
87
+ 不要求本机已经安装 Node.js。需要仓库已有带 `sdkvm.tgz` 与 `SHA256SUMS` 的 GitHub Release(打 `v*` tag 后由 CI 上传)。
68
88
 
69
- | 依赖 | 版本 | 说明 |
70
- |---|---|---|
71
- | Node.js | >= 18.15 | 唯一运行时依赖(CLI 本身另需 commander / picocolors,随包安装) |
72
- | 操作系统 | — | macOS(Apple Silicon / Intel)/ 主流 Linux 发行版 / Windows 10+ |
73
- | 解压工具 | 系统自带 | macOS/Linux 用 `tar`;Windows 用系统自带 bsdtar,缺失时回退 PowerShell `Expand-Archive` |
89
+ macOS / Linux:
74
90
 
75
- > **平台差异须知**
76
- >
77
- > - Linux 解压 Flutter 归档(`.tar.xz`)需系统装有 `xz`(`xz-utils`);主流发行版默认自带
78
- > - Flutter 官方在 Linux / Windows 只发布 **x64** 归档;ARM Linux / ARM Windows 无法安装(macOS 两种架构均支持)
79
- > - `flutter` 命令首次运行会做内部初始化(构建 cache),耗时较久属正常现象
91
+ ```sh
92
+ curl -fsSL https://raw.githubusercontent.com/QInJ1995/sdkvm/main/install.sh | sh
93
+ ```
80
94
 
81
- ## 安装
95
+ Windows(PowerShell):
96
+
97
+ ```powershell
98
+ irm https://raw.githubusercontent.com/QInJ1995/sdkvm/main/install.ps1 | iex
99
+ ```
100
+
101
+ 脚本会:
102
+
103
+ 1. 下载 Node.js 22.20.0 到 `~/.sdkvm/runtime`。它只启动 CLI,`sdkvm node use` 不会改到它。
104
+ 2. 从 GitHub Release 下载 `sdkvm.tgz`,校验 SHA-256 后解压到 `~/.sdkvm/cli`。
105
+ 3. 写入 `~/.local/bin/sdkvm`(Windows 为 `%USERPROFILE%\.local\bin\sdkvm.cmd`)。目录不在 `PATH` 中时,脚本会打印需要追加的那一行。
106
+
107
+ 数据根与 CLI 一致:`SDKVM_HOME` 可覆盖,默认 `~/.sdkvm`。runtime 与 CLI 都落在该根下。国内可换下载前缀:
82
108
 
83
109
  ```sh
84
- npm install -g sdkvm
110
+ SDKVM_NODE_DIST=https://npmmirror.com/mirrors/node \
111
+ SDKVM_RELEASE_BASE=https://github.com/QInJ1995/sdkvm/releases \
112
+ sh install.sh
85
113
  ```
86
114
 
87
- 安装完成后即可使用 `sdkvm` 命令。验证:
115
+ 验证:
88
116
 
89
117
  ```console
90
118
  $ sdkvm version
91
- 1.0.0
119
+ 1.0.1
92
120
  ```
93
121
 
122
+ ## 升级
123
+
124
+ | 安装方式 | 命令 | 影响范围 |
125
+ |---|---|---|
126
+ | npm | `npm update -g sdkvm` | 只更新 CLI。pnpm / yarn / bun 用各自的全局更新命令 |
127
+ | 脚本 | `sdkvm upgrade` | 只替换 `~/.sdkvm/cli`。runtime 与已安装的 SDK 保持不变 |
128
+
129
+ 数据目录 `~/.sdkvm` 与 CLI 升级无关。脚本安装也可以重新执行安装脚本。
130
+
94
131
  ## 快速开始
95
132
 
133
+ Java 可用裸命令(与 `sdkvm java` 等价);Go / Flutter / Node 用子命令。
134
+
96
135
  ```sh
97
- # Java(裸命令 = java,与 easy-jvm 时代用法完全一致)
98
- sdkvm install lts # 安装最新 LTS(当前为 Temurin 25)
99
- sdkvm use 25 # 切换到该版本
100
- java -version # 验证生效(可能需要重开终端)
101
-
102
- # Go(go 子命令组)
103
- sdkvm go install 1.24 # 安装 Go 1.24 线最新补丁版
104
- sdkvm go use 1.24 # 切换(更新 GOROOT / PATH)
136
+ # 可选:国内加速(按 SDK 类型分别设置,互不影响)
137
+ sdkvm mirror use nju # Java Temurin
138
+ sdkvm go mirror use nju
139
+ sdkvm flutter mirror use nju
140
+ sdkvm node mirror use nju
141
+ sdkvm nrm use taobao # 仅影响 npm install,与上面的 mirror 无关
142
+
143
+ # Java
144
+ sdkvm install lts
145
+ sdkvm use 25
146
+ java -version
147
+
148
+ # Go
149
+ sdkvm go install 1.24
150
+ sdkvm go use 1.24
105
151
  go version
106
152
 
107
- # Flutter(flutter 子命令组)
108
- sdkvm flutter install 3.47 # 安装 3.47 线最新补丁版(stable 通道)
109
- sdkvm flutter use 3.47 # 切换(更新 FLUTTER_ROOT / PATH)
153
+ # Flutter(stable)
154
+ sdkvm flutter install 3.47
155
+ sdkvm flutter use 3.47
110
156
  flutter --version
111
157
 
112
- # 混合使用
113
- sdkvm current # 同时显示 java / go / flutter 的当前版本
158
+ # Node.js(npm 随该版本一起切换)
159
+ sdkvm node install lts
160
+ sdkvm node use 24
161
+ node --version
162
+
163
+ # 查看与卸载
164
+ sdkvm current
114
165
  sdkvm java install 21 --vendor zulu
115
166
  sdkvm java use zulu-21
116
- sdkvm ls # 已装的 Java
117
- sdkvm go ls # 已装的 Go
118
- sdkvm flutter ls # 已装的 Flutter
167
+ sdkvm ls
168
+ sdkvm go ls
119
169
  sdkvm uninstall zulu-21
120
- sdkvm go uninstall 1.24
121
170
  ```
122
171
 
172
+ 首次 `use` 后请**重开终端**,或在 macOS / Linux 上 `source ~/.zshrc`(bash 则 source 对应 rc)。IDE 需重启才会读到新的环境变量。
173
+
174
+ 日常只记三条:`install` → `use` → `current` / `ls`。镜像与 npm 源见[镜像与 npm 源](#镜像与-npm-源)。
175
+
123
176
  ## 命令参考
124
177
 
125
- Java 用裸命令(`sdkvm install …`)或 `sdkvm java …` 子命令组,两者完全等价;Go / Flutter 用 `sdkvm go …` / `sdkvm flutter …`。
178
+ Java 使用裸命令(`sdkvm install`)或 `sdkvm java`,两者等价。Go、Flutter、Node.js 分别使用 `sdkvm go`、`sdkvm flutter`、`sdkvm node`。
126
179
 
127
180
  ### 命令速查
128
181
 
129
182
  | 命令 | 作用 |
130
183
  |---|---|
131
- | `sdkvm install <version>` | 安装 Java 版本(= `sdkvm java install`) |
132
- | `sdkvm use <version>` | 切换当前 Java 版本 |
133
- | `sdkvm ls` / `sdkvm ls -r` | 列出已装版本 / 可安装版本线 |
134
- | `sdkvm current` | 显示全部 SDK 类型的当前版本 |
184
+ | `sdkvm install <version>` | 安装 Java(等于 `sdkvm java install`) |
185
+ | `sdkvm use <version>` | 切换当前 Java |
186
+ | `sdkvm ls` / `sdkvm ls -r` | 列出已安装版本 / 可安装版本线 |
187
+ | `sdkvm current` | 显示全部 SDK 的当前版本 |
135
188
  | `sdkvm uninstall <version>` | 卸载一个版本 |
136
- | `sdkvm mirror show·set·unset` | 管理下载镜像 |
137
- | `sdkvm java · go · flutter …` | 各 SDK 类型的完整命令组 |
138
- | `sdkvm version` | 打印 CLI 版本号 |
189
+ | `sdkvm mirror ls\|use\|current\|show\|set\|unset` | 管理 SDK 下载镜像站 / URL(安装包,不是 npm 包源) |
190
+ | `sdkvm nrm ls\|use\|current\|add\|del\|test` | 管理用户级 npm registry(类似 nrm) |
191
+ | `sdkvm java\|go\|flutter\|node …` | 各 SDK 的完整命令组 |
192
+ | `sdkvm version` | 打印 CLI 版本(同 `sdkvm --version`) |
193
+ | `sdkvm upgrade` | 升级 CLI。见[升级](#升级) |
139
194
 
140
- 各类型的版本语法速查:
195
+ 版本写法:
141
196
 
142
197
  ```sh
143
198
  sdkvm java install lts | 21 | 21.0.5 | 21.0.5+11 | zulu-21
144
199
  sdkvm go install latest | 1.24 | 1.24.5 | golang-1.24
145
200
  sdkvm flutter install latest | 3.47 | 3.47.5 | 3.49.0-0.1.pre | flutter-3.47
201
+ sdkvm node install lts | latest | 22 | 22.20.0 | nodejs-22.20.0
146
202
  ```
147
203
 
148
204
  ### `sdkvm install <version>`
149
205
 
150
- 解析 → 下载(实时进度、边下边算 sha256)→ 校验 → 解压到临时目录 → 原子落位:
206
+ 流程:解析、下载(边下边计算 SHA-256)、校验、解压到临时目录、原子落位。
151
207
 
152
208
  ```console
153
209
  $ sdkvm install 21
@@ -160,27 +216,28 @@ sdkvm switch to it: sdkvm use 21
160
216
 
161
217
  | 选项 | 说明 |
162
218
  |---|---|
163
- | `--vendor <id>` | 指定发行版:`temurin`(默认)/ `zulu` / `corretto`;Go 只有 `golang`,Flutter 只有 `flutter` |
164
- | `--force` | 已安装时移除重装(默认跳过已装版本) |
219
+ | `--vendor <id>` | Java:`temurin`(默认)/ `zulu` / `corretto`。Go 为 `golang`,Flutter 为 `flutter`,Node.js 为 `nodejs` |
220
+ | `--force` | 已安装时删除并重装。默认跳过已安装版本 |
165
221
 
166
- 失败行为:校验不过 / 解压异常会自动清理半成品目录与缓存,不留脏状态;下载采用 60 秒**空闲超时**(60s 无数据才中止,大文件不会被总时长掐断)。
222
+ 校验失败或解压异常时,半成品目录和缓存会被清掉。下载超时是 60 秒无数据,不是总时长上限。
167
223
 
168
224
  ### `sdkvm use <version>`
169
225
 
170
- 切换当前版本:更新 `current` 链接与 `JAVA_HOME`(或 `GOROOT` / `FLUTTER_ROOT`)/ `PATH`。版本语法与 `install` 相同,在**已安装**范围内匹配:
226
+ 在已安装版本中匹配,并更新对应的 `current-*` 链接与 `JAVA_HOME` / `GO_HOME` / `FLUTTER_HOME` / `NODE_HOME` / `PATH`。
171
227
 
172
228
  ```sh
173
- sdkvm use 21 # 切换到已安装的 21 最新补丁版
174
- sdkvm use temurin-21.0.5+11 # 切换到精确版本
175
- sdkvm go use 1.24.5 # Go 精确版本
176
- sdkvm flutter use 3.47.5 # Flutter 精确版本
229
+ sdkvm use 21
230
+ sdkvm use temurin-21.0.5+11
231
+ sdkvm go use 1.24.5
232
+ sdkvm flutter use 3.47.5
233
+ sdkvm node use 22.20.0
177
234
  ```
178
235
 
179
- > macOS / Linux 下首次 `use` 会在 shell 配置文件中追加初始化代码块,**重开终端(或 `source ~/.zshrc`)后生效**;之后每次切换只动链接,新终端即时生效。IDE(IntelliJ / VS Code 等)需要重启才会读到新的环境变量。详见[切换机制](#切换机制)。
236
+ macOS / Linux 上,首次 `use` 会向 shell 配置追加初始化块,重开终端或 `source ~/.zshrc` 后生效。之后的切换只改链接。IDE 需要重启才会读到新的环境变量。详见[切换机制](#切换机制)。
180
237
 
181
- ### `sdkvm ls` / `sdkvm list`
238
+ ### `sdkvm ls`
182
239
 
183
- 列出已安装的版本,`→` 标记当前版本:
240
+ 列出已安装版本,`→` 表示当前版本。
184
241
 
185
242
  ```console
186
243
  $ sdkvm go ls
@@ -188,9 +245,7 @@ $ sdkvm go ls
188
245
  golang-1.23.9
189
246
  ```
190
247
 
191
- ### `sdkvm ls -r` / `sdkvm ls --remote`
192
-
193
- 并行拉取该类型全部厂商的可安装版本线。每行名称带厂商前缀,**可直接复制给 `install`**(默认展示最近 12 条线,更老的版本可按精确名称安装):
248
+ `sdkvm ls -r`(`--remote`)并行拉取该类型全部厂商的可安装版本线。行首名称可以直接交给 `install`。默认显示最近 12 条线,更老的版本按精确名称安装。
194
249
 
195
250
  ```console
196
251
  $ sdkvm flutter ls -r
@@ -198,94 +253,116 @@ $ sdkvm flutter ls -r
198
253
  # Flutter (official)
199
254
  flutter-3.47 latest: flutter-3.47.5
200
255
  flutter-3.44 latest: flutter-3.44.9
201
- ...
202
256
 
203
257
  # install with: sdkvm flutter install <name>
204
258
  ```
205
259
 
206
- | 选项 | 说明 |
207
- |---|---|
208
- | `--vendor <id>` | 只列出指定厂商 |
260
+ `--vendor <id>` 只列出一个厂商。
209
261
 
210
262
  ### `sdkvm current`
211
263
 
212
- 显示全部 SDK 类型的当前版本及其环境变量路径(未安装的类型不显示):
264
+ 未安装的类型不显示。
213
265
 
214
266
  ```console
215
267
  $ sdkvm current
216
268
  java: temurin-21.0.12.1
217
269
  JAVA_HOME → ~/.sdkvm/jdks/temurin-21.0.12.1
218
270
  go: golang-1.24.5
219
- GOROOT → ~/.sdkvm/gos/golang-1.24.5
271
+ GO_HOME → ~/.sdkvm/gos/golang-1.24.5
220
272
  flutter: flutter-3.47.5
221
- FLUTTER_ROOT → ~/.sdkvm/flutters/flutter-3.47.5
273
+ FLUTTER_HOME → ~/.sdkvm/flutters/flutter-3.47.5
274
+ node: nodejs-22.20.0
275
+ NODE_HOME → ~/.sdkvm/nodes/nodejs-22.20.0
222
276
  ```
223
277
 
224
278
  ### `sdkvm uninstall <version>`
225
279
 
226
- 卸载已安装的版本,语法与 `use` 相同。卸载当前版本时会自动清空对应 `current` 链接并提示另选版本;不影响其他已装版本。
280
+ 语法与 `use` 相同。卸载当前版本时会清掉对应的 `current-*` 链接,并提示另选版本。其他已安装版本保留。
227
281
 
228
- ### `sdkvm mirror <action> [vendor] [url]`
282
+ ### `sdkvm mirror`
229
283
 
230
- 管理下载镜像,详见[镜像加速](#镜像加速国内用户)。Java / Go / Flutter 分别用 `sdkvm mirror …`、`sdkvm go mirror …`、`sdkvm flutter mirror …`:
284
+ 按 SDK 类型管理**安装包下载镜像**(不是 npm 包源)。Java:`sdkvm mirror`;其余:`sdkvm go|flutter|node mirror`。作用域互不影响。
285
+
286
+ ```sh
287
+ sdkvm mirror ls
288
+ sdkvm mirror use nju
289
+ sdkvm go mirror use aliyun
290
+ sdkvm node mirror use official # 恢复该类型官方源
291
+ ```
231
292
 
232
- | Action | 说明 |
293
+ | 动作 | 说明 |
233
294
  |---|---|
234
- | `show` | 查看当前镜像配置(含推荐值) |
235
- | `set <vendor> <url>` | 设置镜像,写入配置文件 |
236
- | `unset <vendor>` | 恢复官方源 |
295
+ | `ls` / `current` / `show` | 查看本类型可用站与当前配置 |
296
+ | `use <site>` | 一键切换内置站(`nju` / `tuna` / `aliyun` / `huawei` / `official`) |
297
+ | `set [vendor] <url>` / `unset` | 手填或清除 URL |
237
298
 
238
- ### `sdkvm version`
299
+ 站点覆盖与手填示例见[镜像与 npm 源](#镜像与-npm-源)。
300
+
301
+ ### `sdkvm nrm`
302
+
303
+ 管理用户级 **npm registry**(`npm install` 拉包地址),风格接近 [nrm](https://github.com/Pana/nrm)。与 `mirror` 无关。
304
+
305
+ ```sh
306
+ sdkvm nrm ls
307
+ sdkvm nrm use taobao
308
+ sdkvm nrm use npm
309
+ sdkvm nrm add myprivate http://xxx/registry
310
+ sdkvm nrm del myprivate
311
+ sdkvm nrm test
312
+ ```
239
313
 
240
- 打印 CLI 版本号(等同于 `sdkvm --version`)。
314
+ 内置名:`npm`、`yarn`、`taobao`(别名 `npmmirror`)、`tencent`、`cnpm`、`huawei`、`npmMirror`。需要 PATH 上已有 `npm`。
241
315
 
242
316
  ## 版本语法
243
317
 
244
- `install` / `use` / `uninstall` 共用版本语法,按 SDK 类型区分:
318
+ `install`、`use`、`uninstall` 共用下表。未列出的组合会被拒绝并给出改写提示。
245
319
 
246
- | 语法 | Java 含义 | Go 含义 | Flutter 含义 | 示例 |
247
- |---|---|---|---|---|
248
- | `<major>` | 该大版本最新补丁版(`21`) | — | —(裸大版本拒绝,建议 `latest`) | `21` |
249
- | `<major.minor>` | — | 该 minor 线最新补丁版 | 该 minor 线最新补丁版(stable 通道) | `1.24`、`3.47` |
250
- | `lts` | 最新 LTS 大版本 | —(无 LTS) | —(无 LTS) | `lts` |
251
- | `latest` | — | 全局最新稳定版 | stable 通道最新(不追 beta) | `latest` |
252
- | `<full-version>` | 精确版本 / 前缀匹配 | 精确版本 | 精确版本,可带 prerelease 段装 beta | `21.0.5+11`、`1.24.5`、`3.49.0-0.1.pre` |
253
- | `<vendor>-…` | 加厂商前缀限定发行版 | 同左 | 同左 | `zulu-21`、`golang-1.24`、`flutter-3.47` |
320
+ | 语法 | Java | Go | Flutter | Node.js | 示例 |
321
+ |---|---|---|---|---|---|
322
+ | `<major>` | 该大版本最新补丁 | — | — | 该 major 最新 | `21`、`22` |
323
+ | `<major.minor>` | — | 该 minor 线最新补丁 | stable 通道该 minor 线最新补丁 | — | `1.24`、`3.47` |
324
+ | `lts` | 最新 LTS 大版本 | — | — | 最新 LTS 线(当前 24 Krypton) | `lts` |
325
+ | `latest` | — | 最新稳定版 | stable 最新,不含 beta | 最新 Current | `latest` |
326
+ | `<full-version>` | 精确版本或前缀 | 精确版本 | 精确版本,可含 prerelease | 精确版本 | `21.0.5+11`、`1.24.5`、`3.49.0-0.1.pre`、`22.20.0` |
327
+ | `<vendor>-…` | 限定发行版 | 同左 | 同左 | 同左 | `zulu-21`、`golang-1.24`、`nodejs-22.20.0` |
254
328
 
255
329
  匹配规则:
256
330
 
257
- - `21` 匹配该大版本下**已安装/可安装的最新补丁版**;`1.24`、`3.47` 同理匹配该线最新补丁版
258
- - Java 的 `21.0.5` 做前缀匹配,可命中 `21.0.5+11`;Go / Flutter 的精确版本为全串匹配
259
- - Flutter 的 `latest` / `3.47` 只在 **stable** 通道解析;装 beta 需给完整 prerelease 版本号(如 `3.49.0-0.1.pre`)
260
- - Java 的 `lts` 当前指 8 / 11 / 17 / 21 / 25(与 Adoptium LTS 列表对齐)
261
- - 不带厂商前缀时使用默认发行版(仅 Java 可配,见[配置文件](#配置文件);Go / Flutter 各只有一个官方源)
331
+ - `21`、`1.24`、`3.47`、`22` 匹配该线已安装或可安装的最新补丁。
332
+ - Java 的 `21.0.5` 做前缀匹配,可以命中 `21.0.5+11`。Go、Flutter、Node.js 的精确版本按全串匹配。
333
+ - Flutter 的 `latest` 与 `3.47` 只解析 stable。安装 beta 需要完整 prerelease,例如 `3.49.0-0.1.pre`。
334
+ - Java 的 `lts` 与 Adoptium 列表对齐,当前为 8 / 11 / 17 / 21 / 25。Node.js 的 `lts` 取官方 `index.json` 里最新带 LTS 代号的条目。
335
+ - Node.js 不接受 `22.20` 这种两段式,应写成 `22` 或 `22.20.0`。
336
+ - 省略厂商前缀时使用默认发行版。只有 Java 可以配置默认厂商,见[配置文件](#配置文件)。
262
337
 
263
338
  ## 工作原理
264
339
 
265
340
  ### 目录布局
266
341
 
267
- 所有数据位于 `~/.sdkvm/`(Windows 为 `%USERPROFILE%\.sdkvm`;可用 `SDKVM_HOME` 覆盖,旧名 `JVM_HOME` 仍识别):
342
+ 数据根目录是 `~/.sdkvm`(Windows 为 `%USERPROFILE%\.sdkvm`)。`SDKVM_HOME` 可覆盖。
268
343
 
269
344
  ```
270
345
  ~/.sdkvm/
271
- ├── jdks/ # Java:<vendor>-<version>,如 temurin-21.0.12.1
272
- ├── gos/ # Go:golang-<version>,如 golang-1.24.5
273
- ├── flutters/ # Flutter:flutter-<version>,如 flutter-3.47.5
274
- ├── current-java # 指向当前 JAVA_HOME 的链接(Windows 上为 junction)
275
- ├── current-go # 指向当前 GOROOT 的链接
276
- ├── current-flutter # 指向当前 FLUTTER_ROOT 的链接
277
- ├── config.json # CLI 配置(见「配置」)
278
- ├── cache/ # 下载中转(安装成功后自动清理,不做长期缓存)
279
- └── tmp/ # 解压临时目录(同样自动清理)
346
+ ├── jdks/ # Java:temurin-21.0.12.1
347
+ ├── gos/ # Go:golang-1.24.5
348
+ ├── flutters/ # Flutter:flutter-3.47.5
349
+ ├── nodes/ # Node.js:nodejs-22.20.0
350
+ ├── current-java # JAVA_HOME 链接(Windows 为 junction)
351
+ ├── current-go
352
+ ├── current-flutter
353
+ ├── current-node
354
+ ├── runtime/ # 脚本安装的 CLI 运行时,与 current-node 隔离
355
+ ├── cli/ # 脚本安装的 CLI 包
356
+ ├── config.json
357
+ ├── cache/ # 下载中转,安装成功后删除
358
+ └── tmp/ # 解压临时目录,同样会删除
280
359
  ```
281
360
 
282
- 各版本的磁盘量级(解压后,供规划空间参考):Java 每版本约 300 MB,Go 约 250 MB,Flutter 数 GB(压缩包本身 1–2.2 GB)。
361
+ 解压后的大致体积:Java 约 300 MB,Go 约 250 MB,Node.js 约 100 MB(含捆绑 npm),Flutter 数 GB(压缩包约 1–2.2 GB)。
283
362
 
284
363
  ### 切换机制
285
364
 
286
- **macOS / Linux**
287
-
288
- `current-java` / `current-go` / `current-flutter` 是指向当前版本目录的符号链接。首次 `use` 会在 shell 配置文件(zsh → `~/.zshrc`;bash → `~/.bash_profile` / `~/.bashrc`)追加一段带标记的初始化代码块,三种 SDK 各一块、互不干扰:
365
+ macOS / Linux 上,`current-*` 是指向当前版本目录的符号链接。首次 `use` 会向 shell 配置追加带标记的块:zsh 写入 `~/.zshrc`,bash 写入 `~/.bash_profile` 或 `~/.bashrc`。四种 SDK 各一块。
289
366
 
290
367
  ```sh
291
368
  # >>> sdkvm java init >>>
@@ -294,31 +371,30 @@ case ":$PATH:" in *":$JAVA_HOME/bin:"*) ;; *) export PATH="$JAVA_HOME/bin:$PATH"
294
371
  # <<< sdkvm java init <<<
295
372
 
296
373
  # >>> sdkvm go init >>>
297
- export GOROOT="$HOME/.sdkvm/current-go"
298
- case ":$PATH:" in *":$GOROOT/bin:"*) ;; *) export PATH="$GOROOT/bin:$PATH";; esac
374
+ export GO_HOME="$HOME/.sdkvm/current-go"
375
+ case ":$PATH:" in *":$GO_HOME/bin:"*) ;; *) export PATH="$GO_HOME/bin:$PATH";; esac
299
376
  # <<< sdkvm go init <<<
300
377
 
301
378
  # >>> sdkvm flutter init >>>
302
- export FLUTTER_ROOT="$HOME/.sdkvm/current-flutter"
303
- case ":$PATH:" in *":$FLUTTER_ROOT/bin:"*) ;; *) export PATH="$FLUTTER_ROOT/bin:$PATH";; esac
379
+ export FLUTTER_HOME="$HOME/.sdkvm/current-flutter"
380
+ case ":$PATH:" in *":$FLUTTER_HOME/bin:"*) ;; *) export PATH="$FLUTTER_HOME/bin:$PATH";; esac
304
381
  # <<< sdkvm flutter init <<<
305
- ```
306
382
 
307
- 环境变量指向**链接**而非具体版本目录,因此之后每次 `use` 只改链接指向,已开的终端在下一次 `source` rc 或新开终端时读到新值。
308
-
309
- **Windows**
310
-
311
- `%USERPROFILE%\.sdkvm\current-java` / `current-go` / `current-flutter` 为 junction;`use` 写入用户级 `JAVA_HOME` / `GOROOT` / `FLUTTER_ROOT`,并把 `%JAVA_HOME%\bin`、`%GOROOT%\bin`、`%FLUTTER_ROOT%\bin` 追加到用户 PATH。通过注册表 API 操作并原样保留 `REG_EXPAND_SZ` 类型与 `%VAR%` 引用,避免 `setx` 的 1024 字符截断问题。需要**重开终端**(或重启 IDE)生效。
383
+ # >>> sdkvm node init >>>
384
+ export NODE_HOME="$HOME/.sdkvm/current-node"
385
+ case ":$PATH:" in *":$NODE_HOME/bin:"*) ;; *) export PATH="$NODE_HOME/bin:$PATH";; esac
386
+ # <<< sdkvm node init <<<
387
+ ```
312
388
 
313
- ### 数据迁移
389
+ 环境变量指向链接。之后的 `use` 只改链接,新终端会读到新值。
314
390
 
315
- 首次运行时检测旧版 `~/.jvm/`:存在且 `~/.sdkvm/` 尚未创建时,执行一次原子目录改名,随后重写 `current` 链接(更名为 `current-java`,绝对目标同步改指新路径)、Windows 注册表 `JAVA_HOME` 字面值、shell 配置文件中的旧标记块。`~/.sdkvm/` 已存在时**不自动合并**,仅提示手动处理。详见[从 easy-jvm 升级](#从-easy-jvm-升级)。
391
+ Windows 上,四个 `current-*` 都是 junction。`use` 把用户级环境变量写成 `REG_EXPAND_SZ`,保留 `%VAR%` 引用,避免 `setx` 的 1024 字符截断。PATH 追加 `%JAVA_HOME%\bin`、`%GO_HOME%\bin`、`%FLUTTER_HOME%\bin`。Node.js 的 Windows 归档没有 `bin/`,PATH 项是 `%NODE_HOME%` 本身。需要重开终端或重启 IDE。
316
392
 
317
393
  ## 配置
318
394
 
319
395
  ### 配置文件
320
396
 
321
- `~/.sdkvm/config.json`:
397
+ 路径:`~/.sdkvm/config.json`。文件损坏时会备份为 `config.json.bak` 并回退默认值。
322
398
 
323
399
  ```json
324
400
  {
@@ -327,117 +403,196 @@ case ":$PATH:" in *":$FLUTTER_ROOT/bin:"*) ;; *) export PATH="$FLUTTER_ROOT/bin:
327
403
  "mirror": {
328
404
  "temurin": "https://mirrors.nju.edu.cn/adoptium",
329
405
  "golang": "https://golang.google.cn/dl",
330
- "flutter": "https://mirror.nju.edu.cn/flutter/flutter_infra_release"
406
+ "flutter": "https://mirror.nju.edu.cn/flutter/flutter_infra_release",
407
+ "nodejs": "https://mirror.nju.edu.cn/nodejs-release"
408
+ },
409
+ "npmRegistries": {
410
+ "myprivate": "http://xxx/registry/"
331
411
  }
332
412
  }
333
413
  ```
334
414
 
335
415
  | 字段 | 说明 | 默认值 |
336
416
  |---|---|---|
337
- | `version` | 配置 schema 版本 | `1` |
338
- | `defaultVendor` | Java 不带厂商前缀时的默认发行版 | `"temurin"` |
339
- | `mirror` | 各厂商的镜像 URL(键为全局唯一的厂商 id,跨 SDK 类型) | `{}`(官方源) |
340
-
341
- 配置文件损坏时自动备份为 `config.json.bak` 并回退默认值。
417
+ | `version` | schema 版本 | `1` |
418
+ | `defaultVendor` | Java 省略厂商前缀时的发行版 | `"temurin"` |
419
+ | `mirror` | 厂商 id 到镜像根 URL。id 在全部 SDK 中唯一 | `{}` |
420
+ | `npmRegistries` | `sdkvm nrm add` 写入的自定义 npm 源 | `{}` |
342
421
 
343
422
  ### 环境变量
344
423
 
345
- | 变量 | 旧名别名 | 说明 |
346
- |---|---|---|
347
- | `SDKVM_HOME` | `JVM_HOME` | 覆盖数据根目录(默认 `~/.sdkvm`) |
348
- | `SDKVM_MIRROR` | `JVM_MIRROR` | 临时指定下载镜像,**优先级高于配置文件**(不写入) |
349
- | `SDKVM_QUIET` | `JVM_QUIET` | 设为非空时抑制 info/warn 日志输出 |
424
+ | 变量 | 说明 |
425
+ |---|---|
426
+ | `SDKVM_HOME` | 数据根目录,默认 `~/.sdkvm` |
427
+ | `SDKVM_MIRROR` | 临时镜像,优先级高于配置文件,不写入配置 |
428
+ | `SDKVM_QUIET` | 非空时抑制 info 与 warn |
429
+ | `SDKVM_NODE_DIST` | 安装脚本使用的 Node 发行根 URL |
430
+ | `SDKVM_RELEASE_BASE` | 安装脚本与 `sdkvm upgrade` 使用的 GitHub Release 根 URL |
431
+ | `SDKVM_RUNTIME_NODE` | 安装脚本内置的 Node 版本,默认 `22.20.0` |
350
432
 
351
- 镜像解析优先级:`SDKVM_MIRROR` 环境变量 > `config.mirror[<vendor>]` > 官方源。
433
+ 镜像优先级:`SDKVM_MIRROR` > `config.mirror[<vendor>]` > 官方源。详见[镜像与 npm 源](#镜像与-npm-源)。
352
434
 
353
- ## 镜像加速(国内用户)
435
+ ## 镜像与 npm 源
436
+
437
+ 两套独立能力,不要混用:
438
+
439
+ | | `sdkvm mirror` | `sdkvm nrm` |
440
+ |---|---|---|
441
+ | 改什么 | JDK / Go / Flutter / Node **安装包**下载地址 | **npm 包** registry |
442
+ | 影响 | `sdkvm … install` | `npm install` |
443
+ | 作用域 | 按 SDK 类型分别设置 | 用户级全局 |
354
444
 
355
- Temurin 默认从 GitHub 下载、Go 默认从 go.dev 下载、Flutter 默认从 storage.googleapis.com 下载,国内网络建议切换到镜像:
445
+ ### SDK 安装包镜像
446
+
447
+ 推荐按类型选用内置站(`use` 只写当前类型对应的 vendor;别名:`tsinghua`→`tuna`,`ali`→`aliyun`):
356
448
 
357
449
  ```sh
358
- sdkvm mirror set temurin https://mirrors.nju.edu.cn/adoptium # Java
359
- sdkvm go mirror set golang https://golang.google.cn/dl # Go
360
- sdkvm flutter mirror set flutter https://mirror.nju.edu.cn/flutter/flutter_infra_release # Flutter
450
+ sdkvm mirror use nju
451
+ sdkvm go mirror use nju
452
+ sdkvm flutter mirror use nju
453
+ sdkvm node mirror use nju
361
454
  ```
362
455
 
363
- 也可以用环境变量临时指定(不写入配置):
456
+ | 站点 | Java (temurin) | Go | Flutter | Node.js |
457
+ |---|---|---|---|---|
458
+ | `nju` | ✓ | ✓ | ✓ | ✓ |
459
+ | `tuna` | ✓ | — | ✓ | —(归档不全,未收录) |
460
+ | `aliyun` | — | ✓ | — | ✓ |
461
+ | `huawei` | — | — | — | ✓ |
462
+ | `official` | 清空本类型 | 清空本类型 | 清空本类型 | 清空本类型 |
463
+
464
+ 手填 URL 或临时覆盖:
364
465
 
365
466
  ```sh
467
+ sdkvm go mirror set golang https://golang.google.cn/dl
366
468
  SDKVM_MIRROR=https://golang.google.cn/dl sdkvm go install 1.24
367
469
  ```
368
470
 
369
- > 镜像仅替换 tarball 下载地址,版本元数据与校验和**始终走官方 API**——即使文件来自镜像,sha256 仍与官方清单核对。Go 镜像根 URL 兼容 `https://golang.google.cn/dl`(官方中国站)与 `https://mirrors.aliyun.com/golang`(文件名直接拼接);Flutter 镜像为桶前缀替换(已验证 [NJU](https://mirror.nju.edu.cn/flutter/flutter_infra_release);`storage.flutter-io.cn` 不含发布清单,勿用);Zulu 与 Corretto 由官方 CDN 直接分发,暂不支持镜像。
471
+ 优先级:`SDKVM_MIRROR` > `config.mirror[<vendor>]` > 官方源。镜像只替换归档下载地址;版本元数据与校验和仍走官方 API。走镜像时若官方校验源不可达,安装会**硬失败**(避免无法核对的包被放行)。
472
+
473
+ | 厂商 | 说明 |
474
+ |---|---|
475
+ | Temurin | Adoptium 目录结构;已验证 [NJU](https://mirrors.nju.edu.cn/adoptium)、[TUNA](https://mirrors.tuna.tsinghua.edu.cn/Adoptium) |
476
+ | Go | 文件名拼在根 URL 后;如 `nju` / `aliyun` |
477
+ | Flutter | 桶前缀替换;已验证 [NJU](https://mirror.nju.edu.cn/flutter/flutter_infra_release)。不要用 `storage.flutter-io.cn`(无发布清单) |
478
+ | Node.js | 前缀替换;已验证 [NJU](https://mirror.nju.edu.cn/nodejs-release)。不要用 TUNA nodejs-release(缺归档) |
479
+ | Zulu、Corretto | 官方 CDN 直发,暂不支持镜像 |
480
+
481
+ ### npm registry
482
+
483
+ ```sh
484
+ sdkvm nrm use taobao # 国内常用
485
+ sdkvm nrm use npm # 恢复官方
486
+ sdkvm nrm test # 测延迟
487
+ ```
370
488
 
371
489
  ## 安全性
372
490
 
373
- - 下载地址通过**官方 API** 解析(Adoptium API / Azul Metadata API / Corretto 官方分发 / go.dev/dl JSON API / Flutter releases 清单),不做任何搜索页抓取
374
- - tarball 做逐块流式 **SHA-256 校验**:Go 与 Flutter 的校验和内联于官方 API,**强制校验**;Java 各源尽力校验,校验源不可达时警告放行
375
- - 解压前校验归档结构(单根目录、可执行文件存在),且只解压到全新空目录,防止路径穿越
376
- - 安装全程持有文件锁(`~/.sdkvm/.lock`),避免并发安装互相踩踏
491
+ - 下载地址来自官方 API:Adoptium、Azul Metadata、Corretto、go.dev/dl、Flutter releases、nodejs.org/dist `index.json`。不抓取搜索页。
492
+ - 归档按块计算 SHA-256。Go、Flutter、Node.js(官方 `SHASUMS256.txt`)校验失败即中止。Java 校验源不可达时:官方源警告并继续;**走镜像下载时硬失败**(避免无法核对的镜像包被放行)。
493
+ - 解压后检查单根目录和可执行文件,并且只解压到新的空目录。
494
+ - 安装与 `sdkvm upgrade` 持有 `~/.sdkvm/.lock`,避免并发写互相覆盖。
377
495
 
378
496
  ## 常见问题
379
497
 
380
- **Q:`use` 之后 `java -version` 还是旧版本?**
381
- rc 代码块只在**新终端**(或 `source ~/.zshrc`)时生效;IDE 需重启。可先 `sdkvm current` 确认链接已切换,再重开终端。Windows 同理:注册表已更新,但已开的终端读不到新值。
498
+ ### `use` 之后命令还是旧版本
382
499
 
383
- **Q:我用 fish / nushell,rc 探测不到怎么办?**
384
- 当前自动写入仅支持 zsh / bash。手工把[切换机制](#切换机制)中的代码块翻译到你的 shell 即可(fish 语法:`set -gx JAVA_HOME $HOME/.sdkvm/current-java; fish_add_path $JAVA_HOME/bin`)。
500
+ rc 块在新终端或 `source ~/.zshrc` 之后生效。IDE 需要重启。先用 `sdkvm current` 确认链接已经切换。Windows 上注册表已更新,已打开的终端读不到新值。
385
501
 
386
- **Q:Flutter 下载太慢或中断?**
387
- 配置镜像(见上文 NJU 命令)。sdkvm 的下载超时是「60 秒无数据」而非总时长,稳定慢速不会中断;真中断直接重跑 `install`,无残留状态。
502
+ ### 环境变量从 `GOROOT` / `FLUTTER_ROOT` 改名了
388
503
 
389
- **Q:怎么安装 Flutter beta?**
390
- 给完整 prerelease 版本号:`sdkvm flutter install 3.49.0-0.1.pre`。`latest` 与版本线(`3.47`)只解析 stable 通道。
504
+ 现在统一为 `GO_HOME`、`FLUTTER_HOME`(与 `JAVA_HOME` / `NODE_HOME` 对齐)。升级 CLI 后请对已启用的 SDK 再执行一次 `use`,并删除用户环境里残留的旧变量名(Windows 注册表 / 旧 rc 手工行)。
391
505
 
392
- **Q:公司网络走代理,能用吗?**
393
- 当前版本未内置 HTTP 代理支持(Node fetch 不读 `HTTPS_PROXY`)。可用系统级透明代理,或关注后续版本。
506
+ ### fish 或 nushell
394
507
 
395
- **Q:装回 easy-jvm 会怎样?**
396
- easy-jvm 使用独立的 `~/.jvm`,二者互不破坏,但版本各装各的。建议只用 sdkvm(`~/.jvm` 若再出现,检查是否残留旧全局包)。
508
+ 自动写入只支持 zsh 和 bash。按[切换机制](#切换机制)改写成对应语法。fish 示例:
509
+
510
+ ```fish
511
+ set -gx JAVA_HOME $HOME/.sdkvm/current-java
512
+ set -gx GO_HOME $HOME/.sdkvm/current-go
513
+ set -gx FLUTTER_HOME $HOME/.sdkvm/current-flutter
514
+ set -gx NODE_HOME $HOME/.sdkvm/current-node
515
+ fish_add_path $JAVA_HOME/bin $GO_HOME/bin $FLUTTER_HOME/bin $NODE_HOME/bin
516
+ ```
397
517
 
398
- **Q:sdkvm 自身怎么升级?**
399
- `sdkvm` 由 npm 分发:`npm update -g sdkvm`。数据目录(`~/.sdkvm`)与 CLI 升级无关。
518
+ ### Flutter 下载慢或中断
400
519
 
401
- **Q:CI / 多用户环境想隔离数据?**
402
- 设 `SDKVM_HOME=/path/to/dir` 即可整体重定向(安装、链接、配置全部跟随)。
520
+ 先 `sdkvm flutter mirror use nju`(或 `tuna`)。超时条件是 60 秒没有数据,稳定的慢速不会中断。中断后直接重跑 `install`,不会留下半成品。
521
+
522
+ ### 安装 Flutter beta
523
+
524
+ 使用完整 prerelease,例如 `sdkvm flutter install 3.49.0-0.1.pre`。`latest` 和 `3.47` 只解析 stable。
525
+
526
+ ### CLI 会不会被自己管理的 Node 影响
527
+
528
+ 脚本安装用 `~/.sdkvm/runtime` 启动 CLI,`sdkvm node use` 不影响它。npm 全局安装跟随 `PATH` 上的 `node`;切到 18.15 以前时 CLI 可能无法启动,`sdkvm node use 22` 可以恢复。
529
+
530
+ ### `nrm` 和 `mirror` 有什么区别
531
+
532
+ 见[镜像与 npm 源](#镜像与-npm-源):`nrm` 管 npm 拉包,`mirror` 管 SDK 安装包下载。
533
+
534
+ ### 代理
535
+
536
+ 当前不读取 `HTTPS_PROXY`。可以使用系统级透明代理。
537
+
538
+ ### CI 或多用户隔离
539
+
540
+ 设置 `SDKVM_HOME=/path/to/dir`。安装、链接和配置都跟随该目录。
403
541
 
404
542
  ## 卸载
405
543
 
544
+ npm 安装:
545
+
406
546
  ```sh
407
547
  npm uninstall -g sdkvm
408
- rm -rf ~/.sdkvm # 删除 SDK 数据目录(会删掉所有已装版本,先确认)
409
548
  ```
410
549
 
411
- 并删除 shell 配置文件中 `>>> sdkvm java init >>>`、`>>> sdkvm go init >>>`、`>>> sdkvm flutter init >>>` 各自到 `<<< … <<<` 之间的标记块。
550
+ pnpm、yarn、bun 使用各自的全局卸载命令。
412
551
 
413
- Windows 用户额外需要:在系统设置中删除 `JAVA_HOME` / `GOROOT` / `FLUTTER_ROOT`,并从用户 PATH 移除 `%JAVA_HOME%\bin`、`%GOROOT%\bin`、`%FLUTTER_ROOT%\bin`。
552
+ 脚本安装只删除 shim 和 CLI 运行时,已安装的 SDK 还在:
553
+
554
+ ```sh
555
+ rm -f ~/.local/bin/sdkvm
556
+ rm -rf ~/.sdkvm/cli ~/.sdkvm/runtime
557
+ ```
558
+
559
+ Windows 对应删除 `%USERPROFILE%\.local\bin\sdkvm.cmd`,以及 `%USERPROFILE%\.sdkvm\cli` 与 `%USERPROFILE%\.sdkvm\runtime`。
560
+
561
+ 确认不再需要已安装的 JDK、Go、Flutter、Node.js 之后,再删除数据目录:
562
+
563
+ ```sh
564
+ rm -rf ~/.sdkvm
565
+ ```
566
+
567
+ 同时删除 shell 配置里 `>>> sdkvm java init >>>`、`>>> sdkvm go init >>>`、`>>> sdkvm flutter init >>>`、`>>> sdkvm node init >>>` 到对应 `<<< … <<<` 之间的块。
568
+
569
+ Windows 还需要在系统设置中删除 `JAVA_HOME`、`GO_HOME`、`FLUTTER_HOME`、`NODE_HOME`,并从用户 PATH 移除 `%JAVA_HOME%\bin`、`%GO_HOME%\bin`、`%FLUTTER_HOME%\bin`、`%NODE_HOME%`。
414
570
 
415
571
  ## 开发
416
572
 
417
573
  ```sh
418
574
  git clone https://github.com/QInJ1995/sdkvm.git && cd sdkvm
419
575
  npm install
420
-
421
- npm test # vitest 单元 + 集成测试
422
- npm run typecheck # tsc --noEmit
423
- npm run build # tsup → dist/index.js(本地试用:node dist/index.js …)
576
+ npm test
577
+ npm run typecheck
578
+ npm run build
424
579
  ```
425
580
 
426
- 项目结构:
581
+ `npm run build` 用 tsup 生成 `dist/index.js`。本地试用:`node dist/index.js`。
427
582
 
428
583
  ```
429
584
  src/
430
- ├── cli/ # 命令实现(install / use / ls / uninstall / mirror …)
431
- ├── core/ # 版本解析、安装注册表、配置、迁移、文件锁
432
- ├── sdk/ # SDK 类型描述(java / go / flutter:目录名、环境变量、版本语法)
433
- ├── vendor/ # 发行版适配(temurin / zulu / corretto / golang / flutter)+ 镜像改写
434
- ├── fs/ # 下载 / 校验 / 解压 / 归一化 / 链接
435
- ├── shell/ # rc 探测与写入、Windows 注册表环境变量
436
- ├── net/ # fetch 封装(重试、超时)、流式下载
437
- └── ui/ # 日志、进度条
585
+ ├── cli/ # install / use / ls / uninstall / mirror / nrm / upgrade
586
+ ├── core/ # 版本解析、注册表、配置、文件锁
587
+ ├── sdk/ # java / go / flutter / node 的目录、环境变量、版本语法
588
+ ├── vendor/ # temurin / zulu / corretto / golang / flutter / nodejs 与镜像改写
589
+ ├── fs/ # 解压、目录归一化、链接
590
+ ├── shell/ # rc 写入、Windows 注册表
591
+ ├── net/ # fetch、流式下载、校验
592
+ └── ui/ # 日志与进度
438
593
  ```
439
594
 
440
- 新增一种语言 SDK:在 `src/vendor/` 实现一个厂商模块(`listMajors` + `resolve` 两个方法),在 `src/sdk/` 加一个类型描述(安装目录名、current 链接名、环境变量、版本语法、二进制探测路径),注册进 `sdk/index.ts` 后即获得完整的 install / use / ls / uninstall / mirror 命令组——CLI、切换机制、rc / 注册表写入全部自动泛化。
595
+ 新增一种语言:在 `src/vendor/` 实现 `listMajors` 与 `resolve`,在 `src/sdk/` 增加类型描述(安装目录、current 链接、环境变量、版本语法、二进制路径),并注册到 `sdk/index.ts`。install / use / ls / uninstall / mirror,以及 rc 与注册表写入会跟着生效。
441
596
 
442
597
  ## 许可证
443
598