tanmi-dock 0.9.0 → 0.9.3

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 (65) hide show
  1. package/dist/commands/link.d.ts +27 -1
  2. package/dist/commands/link.d.ts.map +1 -1
  3. package/dist/commands/link.js +470 -297
  4. package/dist/commands/link.js.map +1 -1
  5. package/dist/commands/reset.d.ts +9 -0
  6. package/dist/commands/reset.d.ts.map +1 -0
  7. package/dist/commands/reset.js +280 -0
  8. package/dist/commands/reset.js.map +1 -0
  9. package/dist/commands/status.d.ts.map +1 -1
  10. package/dist/commands/status.js +34 -14
  11. package/dist/commands/status.js.map +1 -1
  12. package/dist/commands/unavailable.d.ts +7 -0
  13. package/dist/commands/unavailable.d.ts.map +1 -0
  14. package/dist/commands/unavailable.js +202 -0
  15. package/dist/commands/unavailable.js.map +1 -0
  16. package/dist/commands/unlink.d.ts.map +1 -1
  17. package/dist/commands/unlink.js +8 -4
  18. package/dist/commands/unlink.js.map +1 -1
  19. package/dist/core/codepac.d.ts +3 -1
  20. package/dist/core/codepac.d.ts.map +1 -1
  21. package/dist/core/codepac.js +5 -4
  22. package/dist/core/codepac.js.map +1 -1
  23. package/dist/core/linker.d.ts +6 -0
  24. package/dist/core/linker.d.ts.map +1 -1
  25. package/dist/core/linker.js +26 -1
  26. package/dist/core/linker.js.map +1 -1
  27. package/dist/core/parser.d.ts +10 -0
  28. package/dist/core/parser.d.ts.map +1 -1
  29. package/dist/core/parser.js +18 -0
  30. package/dist/core/parser.js.map +1 -1
  31. package/dist/core/platform.d.ts +4 -0
  32. package/dist/core/platform.d.ts.map +1 -1
  33. package/dist/core/platform.js +52 -0
  34. package/dist/core/platform.js.map +1 -1
  35. package/dist/core/registry.d.ts +16 -0
  36. package/dist/core/registry.d.ts.map +1 -1
  37. package/dist/core/registry.js +66 -1
  38. package/dist/core/registry.js.map +1 -1
  39. package/dist/index.js +4 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/types/index.d.ts +3 -0
  42. package/dist/types/index.d.ts.map +1 -1
  43. package/dist/types/index.js +1 -0
  44. package/dist/types/index.js.map +1 -1
  45. package/dist/utils/prompt.d.ts +12 -0
  46. package/dist/utils/prompt.d.ts.map +1 -1
  47. package/dist/utils/prompt.js +102 -0
  48. package/dist/utils/prompt.js.map +1 -1
  49. package/package.json +1 -1
  50. package/dist/commands/doctor.d.ts +0 -7
  51. package/dist/commands/doctor.d.ts.map +0 -1
  52. package/dist/commands/doctor.js +0 -178
  53. package/dist/commands/doctor.js.map +0 -1
  54. package/dist/commands/projects.d.ts +0 -7
  55. package/dist/commands/projects.d.ts.map +0 -1
  56. package/dist/commands/projects.js +0 -126
  57. package/dist/commands/projects.js.map +0 -1
  58. package/dist/commands/repair.d.ts +0 -16
  59. package/dist/commands/repair.d.ts.map +0 -1
  60. package/dist/commands/repair.js +0 -364
  61. package/dist/commands/repair.js.map +0 -1
  62. package/dist/commands/verify.d.ts +0 -11
  63. package/dist/commands/verify.d.ts.map +0 -1
  64. package/dist/commands/verify.js +0 -266
  65. package/dist/commands/verify.js.map +0 -1
@@ -1,364 +0,0 @@
1
- /**
2
- * repair 命令 - 修复 Store 和 Registry 问题
3
- */
4
- import fs from 'fs/promises';
5
- import path from 'path';
6
- import { Command } from 'commander';
7
- import { ensureInitialized } from '../core/guard.js';
8
- import { getRegistry } from '../core/registry.js';
9
- import * as store from '../core/store.js';
10
- import { formatSize } from '../utils/disk.js';
11
- import { info, success, error, hint, blank, title, separator } from '../utils/logger.js';
12
- import { confirmAction } from '../utils/prompt.js';
13
- /**
14
- * 创建 repair 命令
15
- */
16
- export function createRepairCommand() {
17
- return new Command('repair')
18
- .description('修复 Store 和 Registry 问题')
19
- .option('--dry-run', '只显示将执行的操作')
20
- .option('--prune', '删除孤立库而非登记')
21
- .option('--force', '跳过确认')
22
- .action(async (options) => {
23
- await ensureInitialized();
24
- await repairIssues(options);
25
- });
26
- }
27
- /**
28
- * 修复问题
29
- */
30
- export async function repairIssues(options) {
31
- title('修复 Store 问题');
32
- blank();
33
- const registry = getRegistry();
34
- await registry.load();
35
- const storePath = await store.getStorePath();
36
- const result = {
37
- danglingLinksRemoved: 0,
38
- orphanLibrariesFixed: 0,
39
- staleProjectsCleaned: 0,
40
- staleReferencesFixed: 0,
41
- };
42
- // 收集问题
43
- const issues = {
44
- danglingLinks: [],
45
- orphanLibraries: [],
46
- staleProjects: [],
47
- staleReferences: [],
48
- };
49
- // 1. 检查过期项目和悬挂链接
50
- info('扫描问题...');
51
- const projects = registry.listProjects();
52
- for (const project of projects) {
53
- const projectHash = registry.hashPath(project.path);
54
- // 检查项目路径是否存在
55
- try {
56
- await fs.access(project.path);
57
- }
58
- catch {
59
- issues.staleProjects.push({ hash: projectHash, path: project.path });
60
- continue;
61
- }
62
- // 检查依赖的符号链接
63
- for (const dep of project.dependencies) {
64
- const linkPath = path.join(project.path, dep.linkedPath);
65
- try {
66
- const stat = await fs.lstat(linkPath);
67
- if (stat.isSymbolicLink()) {
68
- const actualTarget = await fs.readlink(linkPath);
69
- const resolvedTarget = path.resolve(path.dirname(linkPath), actualTarget);
70
- try {
71
- await fs.access(resolvedTarget);
72
- }
73
- catch {
74
- issues.danglingLinks.push({
75
- path: linkPath,
76
- projectHash,
77
- dep: { libName: dep.libName, commit: dep.commit },
78
- });
79
- }
80
- }
81
- }
82
- catch {
83
- // 链接不存在,跳过
84
- }
85
- }
86
- }
87
- // 2. 检查孤立库
88
- try {
89
- const storeEntries = await fs.readdir(storePath);
90
- for (const libName of storeEntries) {
91
- const libPath = path.join(storePath, libName);
92
- const stat = await fs.stat(libPath);
93
- if (!stat.isDirectory())
94
- continue;
95
- const commits = await fs.readdir(libPath);
96
- for (const commit of commits) {
97
- const commitPath = path.join(libPath, commit);
98
- const commitStat = await fs.stat(commitPath);
99
- if (!commitStat.isDirectory())
100
- continue;
101
- const libKey = registry.getLibraryKey(libName, commit);
102
- const libInfo = registry.getLibrary(libKey);
103
- if (!libInfo) {
104
- const size = await getDirSizeRecursive(commitPath);
105
- issues.orphanLibraries.push({ libName, commit, size, path: commitPath });
106
- }
107
- }
108
- }
109
- }
110
- catch {
111
- // Store 目录不存在或无法读取
112
- }
113
- // 3. 检查失效引用(Registry 中 referencedBy 指向的项目没有实际符号链接)
114
- const libraries = registry.listLibraries();
115
- for (const lib of libraries) {
116
- const libKey = registry.getLibraryKey(lib.libName, lib.commit);
117
- for (const projectHash of lib.referencedBy) {
118
- const project = registry.getProject(projectHash);
119
- if (!project) {
120
- // 项目不存在于 registry
121
- issues.staleReferences.push({
122
- libKey,
123
- projectHash,
124
- projectPath: '(项目已删除)',
125
- });
126
- continue;
127
- }
128
- // 检查项目中是否有符号链接指向此库版本
129
- let hasValidLink = false;
130
- const libStorePath = path.join(storePath, lib.libName, lib.commit);
131
- for (const dep of project.dependencies) {
132
- if (dep.libName === lib.libName && dep.commit === lib.commit) {
133
- const linkPath = path.join(project.path, dep.linkedPath);
134
- try {
135
- const stat = await fs.lstat(linkPath);
136
- if (stat.isSymbolicLink()) {
137
- const target = await fs.readlink(linkPath);
138
- const resolvedTarget = path.resolve(path.dirname(linkPath), target);
139
- // 检查链接是否指向此库版本
140
- if (resolvedTarget.startsWith(libStorePath)) {
141
- hasValidLink = true;
142
- break;
143
- }
144
- }
145
- else if (stat.isDirectory()) {
146
- // 多平台模式:检查内部是否有符号链接指向此库
147
- const entries = await fs.readdir(linkPath, { withFileTypes: true });
148
- for (const entry of entries) {
149
- if (entry.isSymbolicLink()) {
150
- const subLinkPath = path.join(linkPath, entry.name);
151
- const subTarget = await fs.readlink(subLinkPath);
152
- const resolvedSubTarget = path.resolve(linkPath, subTarget);
153
- if (resolvedSubTarget.startsWith(libStorePath)) {
154
- hasValidLink = true;
155
- break;
156
- }
157
- }
158
- }
159
- if (hasValidLink)
160
- break;
161
- }
162
- }
163
- catch {
164
- // 链接不存在或无法读取
165
- }
166
- }
167
- }
168
- if (!hasValidLink) {
169
- issues.staleReferences.push({
170
- libKey,
171
- projectHash,
172
- projectPath: project.path,
173
- });
174
- }
175
- }
176
- }
177
- // 显示问题汇总
178
- const totalIssues = issues.danglingLinks.length + issues.orphanLibraries.length + issues.staleProjects.length + issues.staleReferences.length;
179
- if (totalIssues === 0) {
180
- success('没有发现需要修复的问题');
181
- return;
182
- }
183
- blank();
184
- info(`发现 ${totalIssues} 个问题:`);
185
- if (issues.staleProjects.length > 0) {
186
- info(` - ${issues.staleProjects.length} 个过期项目`);
187
- }
188
- if (issues.danglingLinks.length > 0) {
189
- info(` - ${issues.danglingLinks.length} 个悬挂链接`);
190
- }
191
- if (issues.orphanLibraries.length > 0) {
192
- const totalSize = issues.orphanLibraries.reduce((sum, lib) => sum + lib.size, 0);
193
- info(` - ${issues.orphanLibraries.length} 个孤立库 (${formatSize(totalSize)})`);
194
- }
195
- if (issues.staleReferences.length > 0) {
196
- info(` - ${issues.staleReferences.length} 个失效引用`);
197
- }
198
- // dry-run 模式
199
- if (options.dryRun) {
200
- blank();
201
- separator();
202
- info('[dry-run] 将执行以下操作:');
203
- blank();
204
- for (const p of issues.staleProjects) {
205
- info(` 清理过期项目: ${p.path}`);
206
- }
207
- for (const link of issues.danglingLinks) {
208
- info(` 移除悬挂链接: ${link.path}`);
209
- }
210
- for (const lib of issues.orphanLibraries) {
211
- if (options.prune) {
212
- info(` 删除孤立库: ${lib.libName}/${lib.commit.slice(0, 7)} (${formatSize(lib.size)})`);
213
- }
214
- else {
215
- info(` 登记孤立库: ${lib.libName}/${lib.commit.slice(0, 7)}`);
216
- }
217
- }
218
- for (const ref of issues.staleReferences) {
219
- info(` 移除失效引用: ${ref.libKey} <- ${ref.projectPath}`);
220
- }
221
- blank();
222
- hint('移除 --dry-run 选项以执行修复');
223
- return;
224
- }
225
- // 确认执行
226
- if (!options.force) {
227
- blank();
228
- const confirmed = await confirmAction(`确认修复以上 ${totalIssues} 个问题?`, false);
229
- if (!confirmed) {
230
- info('已取消修复');
231
- return;
232
- }
233
- }
234
- // 执行修复
235
- blank();
236
- separator();
237
- info('正在修复...');
238
- blank();
239
- // 3.1 清理过期项目
240
- for (const p of issues.staleProjects) {
241
- try {
242
- registry.removeProject(p.hash);
243
- success(`[ok] 清理过期项目: ${p.path}`);
244
- result.staleProjectsCleaned++;
245
- }
246
- catch (err) {
247
- error(`[err] 清理项目失败: ${p.path} - ${err.message}`);
248
- }
249
- }
250
- // 3.2 移除悬挂链接
251
- for (const link of issues.danglingLinks) {
252
- try {
253
- await fs.unlink(link.path);
254
- // 更新项目依赖
255
- const project = registry.getProject(link.projectHash);
256
- if (project) {
257
- project.dependencies = project.dependencies.filter((d) => !(d.libName === link.dep.libName && d.commit === link.dep.commit));
258
- registry.updateProject(link.projectHash, { dependencies: project.dependencies });
259
- }
260
- success(`[ok] 移除悬挂链接: ${link.path}`);
261
- result.danglingLinksRemoved++;
262
- }
263
- catch (err) {
264
- error(`[err] 移除链接失败: ${link.path} - ${err.message}`);
265
- }
266
- }
267
- // 3.3 处理孤立库
268
- for (const lib of issues.orphanLibraries) {
269
- try {
270
- if (options.prune) {
271
- // 删除孤立库
272
- await fs.rm(lib.path, { recursive: true, force: true });
273
- success(`[ok] 删除孤立库: ${lib.libName}/${lib.commit.slice(0, 7)}`);
274
- }
275
- else {
276
- // 登记到 Registry - LibraryInfo
277
- registry.addLibrary({
278
- libName: lib.libName,
279
- commit: lib.commit,
280
- branch: 'unknown',
281
- url: 'unknown',
282
- platforms: [],
283
- size: lib.size,
284
- referencedBy: [],
285
- createdAt: new Date().toISOString(),
286
- lastAccess: new Date().toISOString(),
287
- });
288
- // 扫描平台子目录并登记 StoreEntry
289
- try {
290
- const entries = await fs.readdir(lib.path, { withFileTypes: true });
291
- for (const entry of entries) {
292
- if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== '_shared') {
293
- const platform = entry.name;
294
- const platformPath = path.join(lib.path, platform);
295
- const platformSize = await getDirSizeRecursive(platformPath);
296
- registry.addStore({
297
- libName: lib.libName,
298
- commit: lib.commit,
299
- platform,
300
- branch: 'unknown',
301
- url: 'unknown',
302
- size: platformSize,
303
- usedBy: [],
304
- createdAt: new Date().toISOString(),
305
- lastAccess: new Date().toISOString(),
306
- });
307
- }
308
- }
309
- }
310
- catch {
311
- // 无法读取目录,跳过 StoreEntry 登记
312
- }
313
- success(`[ok] 登记孤立库: ${lib.libName}/${lib.commit.slice(0, 7)}`);
314
- }
315
- result.orphanLibrariesFixed++;
316
- }
317
- catch (err) {
318
- error(`[err] 处理孤立库失败: ${lib.libName}/${lib.commit.slice(0, 7)} - ${err.message}`);
319
- }
320
- }
321
- // 3.4 修复失效引用
322
- for (const ref of issues.staleReferences) {
323
- try {
324
- registry.removeReference(ref.libKey, ref.projectHash);
325
- success(`[ok] 移除失效引用: ${ref.libKey} <- ${ref.projectPath}`);
326
- result.staleReferencesFixed++;
327
- }
328
- catch (err) {
329
- error(`[err] 移除引用失败: ${ref.libKey} - ${err.message}`);
330
- }
331
- }
332
- // 保存 Registry
333
- await registry.save();
334
- // 结果汇总
335
- blank();
336
- separator();
337
- const totalFixed = result.danglingLinksRemoved + result.orphanLibrariesFixed + result.staleProjectsCleaned + result.staleReferencesFixed;
338
- success(`修复完成: ${totalFixed} 个问题已解决`);
339
- }
340
- /**
341
- * 递归计算目录大小
342
- */
343
- async function getDirSizeRecursive(dirPath) {
344
- let size = 0;
345
- try {
346
- const entries = await fs.readdir(dirPath, { withFileTypes: true });
347
- for (const entry of entries) {
348
- const fullPath = path.join(dirPath, entry.name);
349
- if (entry.isDirectory()) {
350
- size += await getDirSizeRecursive(fullPath);
351
- }
352
- else {
353
- const stat = await fs.stat(fullPath);
354
- size += stat.size;
355
- }
356
- }
357
- }
358
- catch {
359
- // 忽略错误
360
- }
361
- return size;
362
- }
363
- export default createRepairCommand;
364
- //# sourceMappingURL=repair.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"repair.js","sourceRoot":"","sources":["../../src/commands/repair.ts"],"names":[],"mappings":"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"}
@@ -1,11 +0,0 @@
1
- import { Command } from 'commander';
2
- /**
3
- * 创建 verify 命令
4
- */
5
- export declare function createVerifyCommand(): Command;
6
- /**
7
- * 验证完整性
8
- */
9
- export declare function verifyIntegrity(): Promise<void>;
10
- export default createVerifyCommand;
11
- //# sourceMappingURL=verify.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAsOrD;AAwBD,eAAe,mBAAmB,CAAC"}
@@ -1,266 +0,0 @@
1
- /**
2
- * verify 命令 - 验证 Store 和 Registry 完整性
3
- */
4
- import fs from 'fs/promises';
5
- import path from 'path';
6
- import { Command } from 'commander';
7
- import { ensureInitialized } from '../core/guard.js';
8
- import { getRegistry } from '../core/registry.js';
9
- import * as store from '../core/store.js';
10
- import { formatSize } from '../utils/disk.js';
11
- import { info, warn, success, error, hint, blank, title, separator } from '../utils/logger.js';
12
- /**
13
- * 创建 verify 命令
14
- */
15
- export function createVerifyCommand() {
16
- return new Command('verify')
17
- .description('验证 Store 和 Registry 完整性')
18
- .action(async () => {
19
- await ensureInitialized();
20
- await verifyIntegrity();
21
- });
22
- }
23
- /**
24
- * 验证完整性
25
- */
26
- export async function verifyIntegrity() {
27
- title('验证 Store 完整性');
28
- blank();
29
- const registry = getRegistry();
30
- await registry.load();
31
- const result = {
32
- danglingLinks: [],
33
- orphanLibraries: [],
34
- missingLibraries: [],
35
- invalidProjects: [],
36
- staleReferences: [],
37
- };
38
- const storePath = await store.getStorePath();
39
- // 1. 检查项目引用一致性
40
- info('检查项目引用...');
41
- const projects = registry.listProjects();
42
- for (const project of projects) {
43
- // 检查项目路径是否存在
44
- try {
45
- await fs.access(project.path);
46
- }
47
- catch {
48
- result.invalidProjects.push(project.path);
49
- continue;
50
- }
51
- // 检查依赖的符号链接
52
- for (const dep of project.dependencies) {
53
- const linkPath = path.join(project.path, dep.linkedPath);
54
- // 使用依赖记录的平台,或项目的第一个平台
55
- const verifyPlatform = dep.platform ?? project.platforms?.[0] ?? 'macOS';
56
- try {
57
- const stat = await fs.lstat(linkPath);
58
- if (stat.isSymbolicLink()) {
59
- const actualTarget = await fs.readlink(linkPath);
60
- const resolvedTarget = path.resolve(path.dirname(linkPath), actualTarget);
61
- // 检查链接目标是否存在
62
- try {
63
- await fs.access(resolvedTarget);
64
- }
65
- catch {
66
- result.danglingLinks.push({ path: linkPath, target: resolvedTarget });
67
- }
68
- }
69
- }
70
- catch {
71
- // 符号链接不存在,检查库是否在 Store
72
- const exists = await store.exists(dep.libName, dep.commit, verifyPlatform);
73
- if (!exists) {
74
- result.missingLibraries.push({
75
- libName: dep.libName,
76
- commit: dep.commit,
77
- project: project.path,
78
- });
79
- }
80
- }
81
- }
82
- }
83
- // 2. 检查孤立库(Store 中有但 Registry 没有)
84
- info('检查孤立库...');
85
- try {
86
- const storeEntries = await fs.readdir(storePath);
87
- for (const libName of storeEntries) {
88
- const libPath = path.join(storePath, libName);
89
- const stat = await fs.stat(libPath);
90
- if (!stat.isDirectory())
91
- continue;
92
- const commits = await fs.readdir(libPath);
93
- for (const commit of commits) {
94
- const commitPath = path.join(libPath, commit);
95
- const commitStat = await fs.stat(commitPath);
96
- if (!commitStat.isDirectory())
97
- continue;
98
- const libKey = registry.getLibraryKey(libName, commit);
99
- const libInfo = registry.getLibrary(libKey);
100
- if (!libInfo) {
101
- // 计算大小
102
- const size = await getDirSizeRecursive(commitPath);
103
- result.orphanLibraries.push({ libName, commit, size });
104
- }
105
- }
106
- }
107
- }
108
- catch {
109
- // Store 目录不存在或无法读取
110
- }
111
- // 3. 检查失效引用(Registry 中 referencedBy 指向的项目没有实际符号链接)
112
- info('检查引用一致性...');
113
- const libraries = registry.listLibraries();
114
- for (const lib of libraries) {
115
- const libKey = registry.getLibraryKey(lib.libName, lib.commit);
116
- for (const projectHash of lib.referencedBy) {
117
- const project = registry.getProject(projectHash);
118
- if (!project) {
119
- // 项目不存在于 registry
120
- result.staleReferences.push({
121
- libKey,
122
- projectHash,
123
- projectPath: '(项目已删除)',
124
- });
125
- continue;
126
- }
127
- // 检查项目中是否有符号链接指向此库版本
128
- let hasValidLink = false;
129
- const libStorePath = path.join(storePath, lib.libName, lib.commit);
130
- for (const dep of project.dependencies) {
131
- if (dep.libName === lib.libName && dep.commit === lib.commit) {
132
- const linkPath = path.join(project.path, dep.linkedPath);
133
- try {
134
- const stat = await fs.lstat(linkPath);
135
- if (stat.isSymbolicLink()) {
136
- const target = await fs.readlink(linkPath);
137
- const resolvedTarget = path.resolve(path.dirname(linkPath), target);
138
- // 检查链接是否指向此库版本
139
- if (resolvedTarget.startsWith(libStorePath)) {
140
- hasValidLink = true;
141
- break;
142
- }
143
- }
144
- else if (stat.isDirectory()) {
145
- // 多平台模式:检查内部是否有符号链接指向此库
146
- const entries = await fs.readdir(linkPath, { withFileTypes: true });
147
- for (const entry of entries) {
148
- if (entry.isSymbolicLink()) {
149
- const subLinkPath = path.join(linkPath, entry.name);
150
- const subTarget = await fs.readlink(subLinkPath);
151
- const resolvedSubTarget = path.resolve(linkPath, subTarget);
152
- if (resolvedSubTarget.startsWith(libStorePath)) {
153
- hasValidLink = true;
154
- break;
155
- }
156
- }
157
- }
158
- if (hasValidLink)
159
- break;
160
- }
161
- }
162
- catch {
163
- // 链接不存在或无法读取
164
- }
165
- }
166
- }
167
- if (!hasValidLink) {
168
- result.staleReferences.push({
169
- libKey,
170
- projectHash,
171
- projectPath: project.path,
172
- });
173
- }
174
- }
175
- }
176
- // 输出结果
177
- blank();
178
- separator();
179
- // Registry 引用一致性
180
- if (result.invalidProjects.length === 0 && result.missingLibraries.length === 0) {
181
- success('[ok] Registry 引用一致');
182
- }
183
- else {
184
- if (result.invalidProjects.length > 0) {
185
- warn(`[warn] 发现 ${result.invalidProjects.length} 个无效项目`);
186
- for (const p of result.invalidProjects) {
187
- info(` - ${p} -> 路径不存在`);
188
- }
189
- }
190
- if (result.missingLibraries.length > 0) {
191
- error(`[err] 发现 ${result.missingLibraries.length} 个缺失库`);
192
- for (const lib of result.missingLibraries) {
193
- info(` - ${lib.libName}/${lib.commit.slice(0, 7)} (引用自 ${lib.project})`);
194
- }
195
- }
196
- }
197
- // 悬挂链接
198
- if (result.danglingLinks.length === 0) {
199
- success('[ok] 符号链接完整');
200
- }
201
- else {
202
- warn(`[warn] 发现 ${result.danglingLinks.length} 个悬挂链接`);
203
- for (const link of result.danglingLinks) {
204
- info(` - ${link.path} -> 目标不存在`);
205
- }
206
- }
207
- // 孤立库
208
- if (result.orphanLibraries.length === 0) {
209
- success('[ok] 无孤立库');
210
- }
211
- else {
212
- const totalSize = result.orphanLibraries.reduce((sum, lib) => sum + lib.size, 0);
213
- warn(`[warn] 发现 ${result.orphanLibraries.length} 个孤立库 (${formatSize(totalSize)})`);
214
- for (const lib of result.orphanLibraries) {
215
- info(` - ${lib.libName}/${lib.commit.slice(0, 7)} (${formatSize(lib.size)})`);
216
- }
217
- }
218
- // 失效引用
219
- if (result.staleReferences.length === 0) {
220
- success('[ok] 引用关系一致');
221
- }
222
- else {
223
- warn(`[warn] 发现 ${result.staleReferences.length} 个失效引用`);
224
- for (const ref of result.staleReferences) {
225
- info(` - ${ref.libKey} <- ${ref.projectPath}`);
226
- }
227
- }
228
- // 总结和建议
229
- blank();
230
- const hasIssues = result.danglingLinks.length > 0 ||
231
- result.orphanLibraries.length > 0 ||
232
- result.missingLibraries.length > 0 ||
233
- result.invalidProjects.length > 0 ||
234
- result.staleReferences.length > 0;
235
- if (hasIssues) {
236
- hint('建议: 运行 tanmi-dock repair 修复问题');
237
- }
238
- else {
239
- success('Store 完整性验证通过');
240
- }
241
- }
242
- /**
243
- * 递归计算目录大小
244
- */
245
- async function getDirSizeRecursive(dirPath) {
246
- let size = 0;
247
- try {
248
- const entries = await fs.readdir(dirPath, { withFileTypes: true });
249
- for (const entry of entries) {
250
- const fullPath = path.join(dirPath, entry.name);
251
- if (entry.isDirectory()) {
252
- size += await getDirSizeRecursive(fullPath);
253
- }
254
- else {
255
- const stat = await fs.stat(fullPath);
256
- size += stat.size;
257
- }
258
- }
259
- }
260
- catch {
261
- // 忽略错误
262
- }
263
- return size;
264
- }
265
- export default createVerifyCommand;
266
- //# sourceMappingURL=verify.js.map