tanmi-dock 0.4.0-beta.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.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +302 -0
  3. package/dist/commands/clean.d.ts +10 -0
  4. package/dist/commands/clean.d.ts.map +1 -0
  5. package/dist/commands/clean.js +215 -0
  6. package/dist/commands/clean.js.map +1 -0
  7. package/dist/commands/config.d.ts +10 -0
  8. package/dist/commands/config.d.ts.map +1 -0
  9. package/dist/commands/config.js +105 -0
  10. package/dist/commands/config.js.map +1 -0
  11. package/dist/commands/doctor.d.ts +7 -0
  12. package/dist/commands/doctor.d.ts.map +1 -0
  13. package/dist/commands/doctor.js +127 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/init.d.ts +7 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +153 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/link.d.ts +7 -0
  20. package/dist/commands/link.d.ts.map +1 -0
  21. package/dist/commands/link.js +522 -0
  22. package/dist/commands/link.js.map +1 -0
  23. package/dist/commands/migrate.d.ts +7 -0
  24. package/dist/commands/migrate.d.ts.map +1 -0
  25. package/dist/commands/migrate.js +137 -0
  26. package/dist/commands/migrate.js.map +1 -0
  27. package/dist/commands/projects.d.ts +7 -0
  28. package/dist/commands/projects.d.ts.map +1 -0
  29. package/dist/commands/projects.js +126 -0
  30. package/dist/commands/projects.js.map +1 -0
  31. package/dist/commands/repair.d.ts +7 -0
  32. package/dist/commands/repair.d.ts.map +1 -0
  33. package/dist/commands/repair.js +256 -0
  34. package/dist/commands/repair.js.map +1 -0
  35. package/dist/commands/status.d.ts +7 -0
  36. package/dist/commands/status.d.ts.map +1 -0
  37. package/dist/commands/status.js +172 -0
  38. package/dist/commands/status.js.map +1 -0
  39. package/dist/commands/unlink.d.ts +7 -0
  40. package/dist/commands/unlink.d.ts.map +1 -0
  41. package/dist/commands/unlink.js +104 -0
  42. package/dist/commands/unlink.js.map +1 -0
  43. package/dist/commands/verify.d.ts +7 -0
  44. package/dist/commands/verify.d.ts.map +1 -0
  45. package/dist/commands/verify.js +190 -0
  46. package/dist/commands/verify.js.map +1 -0
  47. package/dist/core/codepac.d.ts +79 -0
  48. package/dist/core/codepac.d.ts.map +1 -0
  49. package/dist/core/codepac.js +188 -0
  50. package/dist/core/codepac.js.map +1 -0
  51. package/dist/core/config.d.ts +70 -0
  52. package/dist/core/config.d.ts.map +1 -0
  53. package/dist/core/config.js +210 -0
  54. package/dist/core/config.js.map +1 -0
  55. package/dist/core/guard.d.ts +18 -0
  56. package/dist/core/guard.d.ts.map +1 -0
  57. package/dist/core/guard.js +82 -0
  58. package/dist/core/guard.js.map +1 -0
  59. package/dist/core/linker.d.ts +76 -0
  60. package/dist/core/linker.d.ts.map +1 -0
  61. package/dist/core/linker.js +263 -0
  62. package/dist/core/linker.js.map +1 -0
  63. package/dist/core/parser.d.ts +43 -0
  64. package/dist/core/parser.d.ts.map +1 -0
  65. package/dist/core/parser.js +133 -0
  66. package/dist/core/parser.js.map +1 -0
  67. package/dist/core/platform.d.ts +100 -0
  68. package/dist/core/platform.d.ts.map +1 -0
  69. package/dist/core/platform.js +193 -0
  70. package/dist/core/platform.js.map +1 -0
  71. package/dist/core/registry.d.ts +181 -0
  72. package/dist/core/registry.d.ts.map +1 -0
  73. package/dist/core/registry.js +443 -0
  74. package/dist/core/registry.js.map +1 -0
  75. package/dist/core/store.d.ts +77 -0
  76. package/dist/core/store.d.ts.map +1 -0
  77. package/dist/core/store.js +226 -0
  78. package/dist/core/store.js.map +1 -0
  79. package/dist/core/transaction.d.ts +106 -0
  80. package/dist/core/transaction.d.ts.map +1 -0
  81. package/dist/core/transaction.js +295 -0
  82. package/dist/core/transaction.js.map +1 -0
  83. package/dist/index.d.ts +3 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +84 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/types/index.d.ts +174 -0
  88. package/dist/types/index.d.ts.map +1 -0
  89. package/dist/types/index.js +47 -0
  90. package/dist/types/index.js.map +1 -0
  91. package/dist/utils/disk.d.ts +57 -0
  92. package/dist/utils/disk.d.ts.map +1 -0
  93. package/dist/utils/disk.js +313 -0
  94. package/dist/utils/disk.js.map +1 -0
  95. package/dist/utils/exit-codes.d.ts +42 -0
  96. package/dist/utils/exit-codes.d.ts.map +1 -0
  97. package/dist/utils/exit-codes.js +91 -0
  98. package/dist/utils/exit-codes.js.map +1 -0
  99. package/dist/utils/fs-utils.d.ts +44 -0
  100. package/dist/utils/fs-utils.d.ts.map +1 -0
  101. package/dist/utils/fs-utils.js +107 -0
  102. package/dist/utils/fs-utils.js.map +1 -0
  103. package/dist/utils/global-lock.d.ts +28 -0
  104. package/dist/utils/global-lock.d.ts.map +1 -0
  105. package/dist/utils/global-lock.js +89 -0
  106. package/dist/utils/global-lock.js.map +1 -0
  107. package/dist/utils/lock.d.ts +26 -0
  108. package/dist/utils/lock.d.ts.map +1 -0
  109. package/dist/utils/lock.js +68 -0
  110. package/dist/utils/lock.js.map +1 -0
  111. package/dist/utils/logger.d.ts +98 -0
  112. package/dist/utils/logger.d.ts.map +1 -0
  113. package/dist/utils/logger.js +190 -0
  114. package/dist/utils/logger.js.map +1 -0
  115. package/dist/utils/prompt.d.ts +32 -0
  116. package/dist/utils/prompt.d.ts.map +1 -0
  117. package/dist/utils/prompt.js +131 -0
  118. package/dist/utils/prompt.js.map +1 -0
  119. package/package.json +73 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tanmi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,302 @@
1
+ # TanmiDock
2
+
3
+ 集中型第三方库链接管理工具 - 通过符号链接统一管理多项目共享的第三方依赖库。
4
+
5
+ ## 特性
6
+
7
+ - **集中存储**: 所有第三方库统一存储在一个 Store 目录,避免重复下载
8
+ - **符号链接**: 通过 symlink 将 Store 中的库链接到项目目录,节省磁盘空间
9
+ - **多平台支持**: 支持 macOS/iOS/Android/Windows/Linux/WASM/OHOS 等平台,可同时选择多个平台
10
+ - **按平台下载**: 仅下载所需平台的内容,节省带宽和存储空间
11
+ - **智能识别**: 自动识别已有库,支持吸收本地库到 Store
12
+ - **事务安全**: link 操作支持事务回滚,中断后可恢复
13
+ - **文件锁**: 防止并发操作导致数据损坏
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ # 克隆仓库
19
+ git clone <repo-url>
20
+ cd tanmi-dock
21
+
22
+ # 安装依赖
23
+ npm install
24
+
25
+ # 构建
26
+ npm run build
27
+
28
+ # 全局安装(可选)
29
+ npm link
30
+ ```
31
+
32
+ ## 快速开始
33
+
34
+ ```bash
35
+ # 1. 初始化(首次使用)
36
+ tanmi-dock init
37
+
38
+ # 2. 在项目目录执行链接
39
+ cd your-project
40
+ tanmi-dock link
41
+
42
+ # 3. 查看状态
43
+ tanmi-dock status
44
+ ```
45
+
46
+ ## 命令
47
+
48
+ ### `init` - 初始化
49
+
50
+ 首次使用前初始化 TanmiDock,设置 Store 存储路径。
51
+
52
+ ```bash
53
+ tanmi-dock init [options]
54
+
55
+ 选项:
56
+ --store-path <path> 直接指定存储路径(跳过交互)
57
+ -y, --yes 使用默认设置
58
+ ```
59
+
60
+ ### `link` - 链接依赖
61
+
62
+ 解析项目的 `codepac-dep.json` 配置,将依赖库链接到项目。
63
+
64
+ ```bash
65
+ tanmi-dock link [path] [options]
66
+
67
+ 参数:
68
+ path 项目路径(默认当前目录)
69
+
70
+ 选项:
71
+ -p, --platform <platforms...> 指定平台,可多选 (mac/ios/android/win/linux/wasm/ohos)
72
+ -y, --yes 跳过确认提示
73
+ --no-download 不自动下载缺失库
74
+ --dry-run 只显示将要执行的操作
75
+
76
+ 示例:
77
+ tanmi-dock link # 交互式选择平台
78
+ tanmi-dock link -p mac # 仅 macOS
79
+ tanmi-dock link -p mac ios # macOS + iOS
80
+ tanmi-dock link -p mac ios android # 多平台
81
+ ```
82
+
83
+ 依赖状态处理:
84
+ - **LINKED**: 已正确链接,跳过
85
+ - **RELINK**: 链接目标错误,重建链接
86
+ - **REPLACE**: 本地是目录但 Store 已有,替换为链接
87
+ - **ABSORB**: 本地有目录但 Store 没有,移入 Store 并创建链接
88
+ - **MISSING**: 本地和 Store 都没有,需要下载
89
+ - **LINK_NEW**: Store 有但本地没有,创建链接
90
+
91
+ ### `status` - 查看状态
92
+
93
+ 显示当前项目或 Store 的状态信息。
94
+
95
+ ```bash
96
+ tanmi-dock status [options]
97
+
98
+ 选项:
99
+ -s, --store 显示 Store 状态
100
+ -a, --all 显示所有详细信息
101
+ ```
102
+
103
+ ### `projects` - 项目管理
104
+
105
+ 列出所有已注册的项目。
106
+
107
+ ```bash
108
+ tanmi-dock projects [options]
109
+
110
+ 选项:
111
+ -a, --all 显示详细信息
112
+ ```
113
+
114
+ ### `clean` - 清理
115
+
116
+ 清理未被引用的库,释放磁盘空间。
117
+
118
+ ```bash
119
+ tanmi-dock clean [options]
120
+
121
+ 选项:
122
+ -y, --yes 跳过确认提示
123
+ --dry-run 只显示将要清理的内容
124
+ ```
125
+
126
+ ### `unlink` - 解除链接
127
+
128
+ 解除项目依赖的符号链接,恢复为普通目录。
129
+
130
+ ```bash
131
+ tanmi-dock unlink [path] [options]
132
+
133
+ 参数:
134
+ path 项目路径(默认当前目录)
135
+
136
+ 选项:
137
+ -y, --yes 跳过确认提示
138
+ ```
139
+
140
+ ### `config` - 配置管理
141
+
142
+ 查看或修改配置。
143
+
144
+ ```bash
145
+ tanmi-dock config [key] [value]
146
+
147
+ 参数:
148
+ key 配置项名称
149
+ value 配置值(不提供则显示当前值)
150
+
151
+ 示例:
152
+ tanmi-dock config # 显示所有配置
153
+ tanmi-dock config storePath # 显示 storePath
154
+ tanmi-dock config autoDownload false # 设置 autoDownload
155
+ ```
156
+
157
+ ### `migrate` - 迁移 Store
158
+
159
+ 将 Store 迁移到新位置。
160
+
161
+ ```bash
162
+ tanmi-dock migrate <newPath> [options]
163
+
164
+ 参数:
165
+ newPath 新的 Store 路径
166
+
167
+ 选项:
168
+ --force 跳过确认提示
169
+ --keep-old 保留旧目录(默认删除)
170
+ ```
171
+
172
+ ### `doctor` - 环境诊断
173
+
174
+ 检测运行环境问题。
175
+
176
+ ```bash
177
+ tanmi-dock doctor [options]
178
+
179
+ 选项:
180
+ --json 输出 JSON 格式
181
+ ```
182
+
183
+ 检测内容:
184
+ - codepac 是否已安装
185
+ - 配置文件是否存在
186
+ - Store 目录是否可访问
187
+ - 磁盘空间是否充足
188
+
189
+ ### `verify` - 完整性验证
190
+
191
+ 验证 Store 和 Registry 的完整性。
192
+
193
+ ```bash
194
+ tanmi-dock verify
195
+ ```
196
+
197
+ 检测内容:
198
+ - **悬挂链接**: 符号链接指向的目标不存在
199
+ - **孤立库**: Store 中存在但 Registry 未记录的库
200
+ - **缺失库**: Registry 记录但 Store 中不存在的库
201
+ - **无效项目**: 已注册但路径不存在的项目
202
+
203
+ ### `repair` - 修复问题
204
+
205
+ 修复 verify 检测到的问题。
206
+
207
+ ```bash
208
+ tanmi-dock repair [options]
209
+
210
+ 选项:
211
+ --dry-run 只显示将执行的操作
212
+ --prune 删除孤立库(默认登记到 Registry)
213
+ --force 跳过确认提示
214
+ ```
215
+
216
+ 修复操作:
217
+ - 清理过期项目记录
218
+ - 移除悬挂的符号链接
219
+ - 登记或删除孤立库
220
+
221
+ ## 配置文件
222
+
223
+ ### codepac-dep.json
224
+
225
+ 项目依赖配置文件,定义需要链接的第三方库。
226
+
227
+ ```json
228
+ {
229
+ "version": "1.0.0",
230
+ "vars": {
231
+ "LIBS_ROOT": "../3rdparty"
232
+ },
233
+ "repos": {
234
+ "common": [
235
+ {
236
+ "url": "https://github.com/user/repo.git",
237
+ "commit": "abc1234",
238
+ "branch": "main",
239
+ "dir": "${LIBS_ROOT}/repo"
240
+ }
241
+ ]
242
+ }
243
+ }
244
+ ```
245
+
246
+ ### 全局配置
247
+
248
+ 配置文件位置:
249
+ - macOS/Linux: `~/.tanmi-dock/config.json`
250
+ - Windows: `%USERPROFILE%\.tanmi-dock\config.json`
251
+
252
+ 配置项:
253
+ - `storePath`: Store 存储路径
254
+ - `cleanStrategy`: 清理策略 (`unreferenced` | `lru` | `manual`)
255
+ - `autoDownload`: 是否自动下载缺失库
256
+
257
+ ## 目录结构
258
+
259
+ ```
260
+ Store/
261
+ ├── lib-name-1/
262
+ │ └── abc1234/ # commit hash
263
+ │ ├── macOS/ # macOS 平台内容
264
+ │ ├── iOS/ # iOS 平台内容
265
+ │ └── android/ # Android 平台内容
266
+ └── lib-name-2/
267
+ └── def5678/
268
+ ├── macOS/
269
+ └── Win/
270
+ ```
271
+
272
+ > **说明**: 每个库按 `库名/commit/平台` 的结构存储,支持同一库多平台共存。
273
+
274
+ ## 开发
275
+
276
+ ```bash
277
+ # 开发模式运行
278
+ npm run dev
279
+
280
+ # 运行测试
281
+ npm test
282
+
283
+ # 测试覆盖率
284
+ npm run test:coverage
285
+
286
+ # 代码检查
287
+ npm run lint
288
+
289
+ # 代码格式化
290
+ npm run format
291
+ ```
292
+
293
+ ## 技术栈
294
+
295
+ - TypeScript
296
+ - Commander.js (CLI 框架)
297
+ - Vitest (测试框架)
298
+ - ESLint + Prettier (代码质量)
299
+
300
+ ## 许可
301
+
302
+ MIT
@@ -0,0 +1,10 @@
1
+ /**
2
+ * clean 命令 - 清理无引用库
3
+ */
4
+ import { Command } from 'commander';
5
+ /**
6
+ * 创建 clean 命令
7
+ */
8
+ export declare function createCleanCommand(): Command;
9
+ export default createCleanCommand;
10
+ //# sourceMappingURL=clean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["../../src/commands/clean.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAc5C;AAuND,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,215 @@
1
+ /**
2
+ * clean 命令 - 清理无引用库
3
+ */
4
+ import { Command } from 'commander';
5
+ import { ensureInitialized } from '../core/guard.js';
6
+ import { getRegistry } from '../core/registry.js';
7
+ import * as store from '../core/store.js';
8
+ import * as config from '../core/config.js';
9
+ import { formatSize } from '../utils/disk.js';
10
+ import { info, warn, success, hint, blank, separator, title, error } from '../utils/logger.js';
11
+ import { withGlobalLock } from '../utils/global-lock.js';
12
+ import { confirmAction, checkboxSelect } from '../utils/prompt.js';
13
+ /**
14
+ * 创建 clean 命令
15
+ */
16
+ export function createCleanCommand() {
17
+ return new Command('clean')
18
+ .description('清理无引用的库')
19
+ .option('--dry-run', '只显示将要清理的内容')
20
+ .option('--force', '跳过确认')
21
+ .action(async (options) => {
22
+ await ensureInitialized();
23
+ try {
24
+ await withGlobalLock(() => cleanLibraries(options));
25
+ }
26
+ catch (err) {
27
+ error(err.message);
28
+ process.exit(1);
29
+ }
30
+ });
31
+ }
32
+ /**
33
+ * 清理库
34
+ */
35
+ async function cleanLibraries(options) {
36
+ const registry = getRegistry();
37
+ await registry.load();
38
+ // 获取清理策略配置
39
+ const cleanStrategy = await config.get('cleanStrategy');
40
+ const unusedDays = (await config.get('unusedDays')) ?? 30;
41
+ // 先清理无效项目
42
+ info('扫描 Store...');
43
+ const staleHashes = await registry.cleanStaleProjects();
44
+ if (staleHashes.length > 0) {
45
+ info(`清理了 ${staleHashes.length} 个无效项目记录`);
46
+ }
47
+ // 清理失效的 Store 引用
48
+ const staleRefs = await registry.cleanStaleReferences();
49
+ if (staleRefs > 0) {
50
+ info(`清理了 ${staleRefs} 个失效引用`);
51
+ }
52
+ // 根据策略获取待清理列表
53
+ let toCleanLibs = [];
54
+ let toCleanStores = [];
55
+ let strategyName;
56
+ if (cleanStrategy === 'unused') {
57
+ // unused 策略:基于 StoreEntry 和 unlinkedAt
58
+ toCleanStores = registry.getUnusedStores(unusedDays);
59
+ strategyName = `unused (超过 ${unusedDays} 天)`;
60
+ // 显示待清理的库
61
+ const pending = registry.getPendingUnusedStores(unusedDays);
62
+ if (pending.length > 0) {
63
+ blank();
64
+ info(`无引用但尚未达到清理条件的库 (${pending.length} 个):`);
65
+ for (const { entry, daysLeft } of pending) {
66
+ hint(` - ${entry.libName}/${entry.commit.slice(0, 7)}/${entry.platform} - 还剩 ${daysLeft} 天`);
67
+ }
68
+ }
69
+ }
70
+ else if (cleanStrategy === 'manual') {
71
+ // manual 策略:交互式选择要清理的库
72
+ const allStores = registry.listStores();
73
+ if (allStores.length === 0) {
74
+ success('Store 为空');
75
+ return;
76
+ }
77
+ // 构建选项列表
78
+ const choices = allStores.map((entry) => {
79
+ const key = registry.getStoreKey(entry.libName, entry.commit, entry.platform);
80
+ const status = entry.usedBy.length === 0
81
+ ? '(无引用)'
82
+ : `(被 ${entry.usedBy.length} 个项目使用)`;
83
+ const size = formatSize(entry.size);
84
+ return {
85
+ name: `${entry.libName}/${entry.commit.slice(0, 7)}/${entry.platform} ${size} ${status}`,
86
+ value: key,
87
+ checked: entry.usedBy.length === 0, // 无引用的默认勾选
88
+ };
89
+ });
90
+ blank();
91
+ const selected = await checkboxSelect('选择要清理的库:', choices);
92
+ if (selected.length === 0) {
93
+ info('未选择任何库');
94
+ return;
95
+ }
96
+ // 警告有引用的库
97
+ const withRefs = selected.filter((key) => {
98
+ const entry = registry.getStore(key);
99
+ return entry && entry.usedBy.length > 0;
100
+ });
101
+ if (withRefs.length > 0) {
102
+ blank();
103
+ warn(`注意: ${withRefs.length} 个库仍被项目引用,删除后链接将失效`);
104
+ const confirmed = await confirmAction('确定继续?', false);
105
+ if (!confirmed) {
106
+ info('已取消清理');
107
+ return;
108
+ }
109
+ }
110
+ // 将选中的转为 StoreEntry
111
+ for (const key of selected) {
112
+ const entry = registry.getStore(key);
113
+ if (entry) {
114
+ toCleanStores.push(entry);
115
+ }
116
+ }
117
+ strategyName = 'manual';
118
+ }
119
+ else {
120
+ // unreferenced 策略(默认):基于 LibraryInfo
121
+ toCleanLibs = registry.getUnreferencedLibraries();
122
+ strategyName = 'unreferenced';
123
+ }
124
+ // 检查是否有需要清理的内容
125
+ if (toCleanLibs.length === 0 && toCleanStores.length === 0) {
126
+ success('没有需要清理的库');
127
+ return;
128
+ }
129
+ // 计算总大小
130
+ let totalSize = 0;
131
+ if (toCleanStores.length > 0) {
132
+ for (const entry of toCleanStores) {
133
+ totalSize += entry.size;
134
+ }
135
+ }
136
+ else {
137
+ for (const lib of toCleanLibs) {
138
+ totalSize += lib.size;
139
+ }
140
+ }
141
+ blank();
142
+ title(`将清理 (${strategyName} 策略):`);
143
+ if (toCleanStores.length > 0) {
144
+ for (const entry of toCleanStores) {
145
+ const daysAgo = entry.unlinkedAt
146
+ ? Math.floor((Date.now() - entry.unlinkedAt) / 86400000)
147
+ : 0;
148
+ info(` - ${entry.libName}/${entry.commit.slice(0, 7)}/${entry.platform} (${formatSize(entry.size)}) - 无引用 ${daysAgo} 天`);
149
+ }
150
+ }
151
+ else {
152
+ for (const lib of toCleanLibs) {
153
+ info(` - ${lib.libName}/${lib.commit.slice(0, 7)} (${formatSize(lib.size)}) - 无项目引用`);
154
+ }
155
+ }
156
+ blank();
157
+ info(`总计释放: ${formatSize(totalSize)}`);
158
+ if (options.dryRun) {
159
+ blank();
160
+ hint('运行 tanmi-dock clean 执行清理');
161
+ return;
162
+ }
163
+ const cleanCount = toCleanStores.length > 0 ? toCleanStores.length : toCleanLibs.length;
164
+ if (!options.force) {
165
+ blank();
166
+ const confirmed = await confirmAction(`确认清理以上 ${cleanCount} 个库 (${formatSize(totalSize)})?`, false);
167
+ if (!confirmed) {
168
+ info('已取消清理');
169
+ return;
170
+ }
171
+ }
172
+ // 执行清理
173
+ blank();
174
+ separator();
175
+ info('正在清理...');
176
+ let cleaned = 0;
177
+ let freedSize = 0;
178
+ if (toCleanStores.length > 0) {
179
+ // unused 策略:清理 StoreEntry
180
+ for (const entry of toCleanStores) {
181
+ try {
182
+ await store.remove(entry.libName, entry.commit, entry.platform);
183
+ const storeKey = registry.getStoreKey(entry.libName, entry.commit, entry.platform);
184
+ registry.removeStore(storeKey);
185
+ freedSize += entry.size;
186
+ cleaned++;
187
+ }
188
+ catch (err) {
189
+ warn(`清理 ${entry.libName}/${entry.platform} 失败: ${err.message}`);
190
+ }
191
+ }
192
+ }
193
+ else {
194
+ // unreferenced 策略:清理 LibraryInfo
195
+ for (const lib of toCleanLibs) {
196
+ try {
197
+ for (const platform of lib.platforms) {
198
+ await store.remove(lib.libName, lib.commit, platform);
199
+ }
200
+ const libKey = registry.getLibraryKey(lib.libName, lib.commit);
201
+ registry.removeLibrary(libKey);
202
+ freedSize += lib.size;
203
+ cleaned++;
204
+ }
205
+ catch (err) {
206
+ warn(`清理 ${lib.libName} 失败: ${err.message}`);
207
+ }
208
+ }
209
+ }
210
+ await registry.save();
211
+ blank();
212
+ success(`清理完成: 删除 ${cleaned} 个库,释放 ${formatSize(freedSize)}`);
213
+ }
214
+ export default createCleanCommand;
215
+ //# sourceMappingURL=clean.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.js","sourceRoot":"","sources":["../../src/commands/clean.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * config 命令 - 查看/修改配置
3
+ */
4
+ import { Command } from 'commander';
5
+ /**
6
+ * 创建 config 命令
7
+ */
8
+ export declare function createConfigCommand(): Command;
9
+ export default createConfigCommand;
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CA4B7C;AAkFD,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * config 命令 - 查看/修改配置
3
+ */
4
+ import { Command } from 'commander';
5
+ import { ensureInitialized } from '../core/guard.js';
6
+ import * as config from '../core/config.js';
7
+ import { shrinkHome } from '../core/platform.js';
8
+ import { info, error, success, title, blank } from '../utils/logger.js';
9
+ /**
10
+ * 创建 config 命令
11
+ */
12
+ export function createConfigCommand() {
13
+ const cmd = new Command('config').description('查看或修改配置');
14
+ // 默认显示所有配置
15
+ cmd.action(async () => {
16
+ await ensureInitialized();
17
+ await showConfig();
18
+ });
19
+ // get 子命令
20
+ cmd
21
+ .command('get <key>')
22
+ .description('获取配置项的值')
23
+ .action(async (key) => {
24
+ await ensureInitialized();
25
+ await getConfigValue(key);
26
+ });
27
+ // set 子命令
28
+ cmd
29
+ .command('set <key> <value>')
30
+ .description('设置配置项的值')
31
+ .action(async (key, value) => {
32
+ await ensureInitialized();
33
+ await setConfigValue(key, value);
34
+ });
35
+ return cmd;
36
+ }
37
+ /**
38
+ * 显示所有配置
39
+ */
40
+ async function showConfig() {
41
+ const cfg = await config.load();
42
+ if (!cfg) {
43
+ error('配置文件不存在');
44
+ process.exit(1);
45
+ }
46
+ title('TanmiDock 配置:');
47
+ blank();
48
+ info(` version: ${cfg.version}`);
49
+ info(` storePath: ${shrinkHome(cfg.storePath)}`);
50
+ info(` cleanStrategy: ${cfg.cleanStrategy}`);
51
+ info(` autoDownload: ${cfg.autoDownload}`);
52
+ if (cfg.maxStoreSize) {
53
+ info(` maxStoreSize: ${cfg.maxStoreSize}`);
54
+ }
55
+ blank();
56
+ const { getConfigPath } = await import('../core/platform.js');
57
+ info(`配置文件: ${shrinkHome(getConfigPath())}`);
58
+ }
59
+ /**
60
+ * 获取配置项
61
+ */
62
+ async function getConfigValue(key) {
63
+ if (!config.isValidConfigKey(key)) {
64
+ error(`无效的配置项: ${key}`);
65
+ info('有效的配置项: version, storePath, cleanStrategy, maxStoreSize, autoDownload');
66
+ process.exit(1);
67
+ }
68
+ const value = await config.get(key);
69
+ if (value === undefined) {
70
+ error(`配置项 ${key} 未设置`);
71
+ process.exit(1);
72
+ }
73
+ if (key === 'storePath' && typeof value === 'string') {
74
+ info(shrinkHome(value));
75
+ }
76
+ else {
77
+ info(String(value));
78
+ }
79
+ }
80
+ /**
81
+ * 设置配置项
82
+ */
83
+ async function setConfigValue(key, value) {
84
+ if (!config.isValidConfigKey(key)) {
85
+ error(`无效的配置项: ${key}`);
86
+ info('有效的配置项: version, storePath, cleanStrategy, maxStoreSize, autoDownload');
87
+ process.exit(1);
88
+ }
89
+ // 只读配置项
90
+ if (key === 'version' || key === 'initialized') {
91
+ error(`配置项 ${key} 为只读`);
92
+ process.exit(1);
93
+ }
94
+ try {
95
+ const parsedValue = config.parseConfigValue(key, value);
96
+ await config.set(key, parsedValue);
97
+ success(`配置已更新: ${key} = ${value}`);
98
+ }
99
+ catch (err) {
100
+ error(err.message);
101
+ process.exit(1);
102
+ }
103
+ }
104
+ export default createConfigCommand;
105
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}