lcch-cli 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 +847 -0
- package/dist/backup.js +142 -0
- package/dist/export.js +1211 -0
- package/dist/index.js +3015 -0
- package/dist/scanner.js +1789 -0
- package/dist/types.js +5 -0
- package/package.json +49 -0
package/dist/backup.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 备份管理模块 - 负责备份和恢复
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.getConfigSourcePath = getConfigSourcePath;
|
|
40
|
+
exports.getBackupTargetFromFilename = getBackupTargetFromFilename;
|
|
41
|
+
exports.createBackup = createBackup;
|
|
42
|
+
exports.listBackups = listBackups;
|
|
43
|
+
exports.restoreBackup = restoreBackup;
|
|
44
|
+
exports.deleteBackup = deleteBackup;
|
|
45
|
+
exports.formatFileSize = formatFileSize;
|
|
46
|
+
const fs = __importStar(require("fs-extra"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const os = __importStar(require("os"));
|
|
49
|
+
const scanner_1 = require("./scanner");
|
|
50
|
+
function getLcchDir() {
|
|
51
|
+
return path.join(os.homedir(), '.lcch');
|
|
52
|
+
}
|
|
53
|
+
function getBackupDir(target) {
|
|
54
|
+
const subDir = target === 'config' ? 'config' : 'settings';
|
|
55
|
+
return path.join(getLcchDir(), 'backups', subDir);
|
|
56
|
+
}
|
|
57
|
+
function getConfigSourcePath(target) {
|
|
58
|
+
if (target === 'config') {
|
|
59
|
+
return (0, scanner_1.getConfigPath)();
|
|
60
|
+
}
|
|
61
|
+
return path.join(os.homedir(), '.claude', 'settings.json');
|
|
62
|
+
}
|
|
63
|
+
function getBackupTargetFromFilename(filename) {
|
|
64
|
+
if (filename.startsWith('.claude.json.'))
|
|
65
|
+
return 'config';
|
|
66
|
+
if (filename.startsWith('settings.json.'))
|
|
67
|
+
return 'settings';
|
|
68
|
+
throw new Error(`无法从文件名推断备份类型: ${filename}`);
|
|
69
|
+
}
|
|
70
|
+
function generateBackupFilename(target) {
|
|
71
|
+
const timestamp = Date.now();
|
|
72
|
+
if (target === 'config') {
|
|
73
|
+
return `.claude.json.backup.${timestamp}`;
|
|
74
|
+
}
|
|
75
|
+
return `settings.json.backup.${timestamp}`;
|
|
76
|
+
}
|
|
77
|
+
async function createBackup(target) {
|
|
78
|
+
const sourcePath = getConfigSourcePath(target);
|
|
79
|
+
const backupDir = getBackupDir(target);
|
|
80
|
+
await fs.ensureDir(backupDir);
|
|
81
|
+
const backupFilename = generateBackupFilename(target);
|
|
82
|
+
const backupPath = path.join(backupDir, backupFilename);
|
|
83
|
+
await fs.copy(sourcePath, backupPath);
|
|
84
|
+
return backupPath;
|
|
85
|
+
}
|
|
86
|
+
async function listBackups() {
|
|
87
|
+
const allBackups = [];
|
|
88
|
+
const targets = ['config', 'settings'];
|
|
89
|
+
for (const target of targets) {
|
|
90
|
+
const backupDir = getBackupDir(target);
|
|
91
|
+
if (!await fs.pathExists(backupDir)) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const files = await fs.readdir(backupDir);
|
|
95
|
+
for (const filename of files) {
|
|
96
|
+
if (filename.startsWith('.claude.json.backup') ||
|
|
97
|
+
filename.startsWith('settings.json.backup')) {
|
|
98
|
+
const backupPath = path.join(backupDir, filename);
|
|
99
|
+
const stats = await fs.stat(backupPath);
|
|
100
|
+
allBackups.push({
|
|
101
|
+
filename,
|
|
102
|
+
path: backupPath,
|
|
103
|
+
createdAt: stats.mtime,
|
|
104
|
+
size: stats.size,
|
|
105
|
+
target,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return allBackups.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
111
|
+
}
|
|
112
|
+
async function restoreBackup(backupPath) {
|
|
113
|
+
if (!await fs.pathExists(backupPath)) {
|
|
114
|
+
throw new Error(`备份文件不存在: ${backupPath}`);
|
|
115
|
+
}
|
|
116
|
+
const filename = path.basename(backupPath);
|
|
117
|
+
const target = getBackupTargetFromFilename(filename);
|
|
118
|
+
const sourcePath = getConfigSourcePath(target);
|
|
119
|
+
const backupDir = getBackupDir(target);
|
|
120
|
+
const autoBackupFilename = target === 'config'
|
|
121
|
+
? '.claude.json.backup_auto_before_restore'
|
|
122
|
+
: 'settings.json.backup_auto_before_restore';
|
|
123
|
+
const autoBackupPath = path.join(backupDir, autoBackupFilename);
|
|
124
|
+
await fs.copy(sourcePath, autoBackupPath);
|
|
125
|
+
await fs.copy(backupPath, sourcePath);
|
|
126
|
+
}
|
|
127
|
+
async function deleteBackup(backupPath) {
|
|
128
|
+
if (!await fs.pathExists(backupPath)) {
|
|
129
|
+
throw new Error(`备份文件不存在: ${backupPath}`);
|
|
130
|
+
}
|
|
131
|
+
await fs.remove(backupPath);
|
|
132
|
+
}
|
|
133
|
+
function formatFileSize(bytes) {
|
|
134
|
+
const units = ['B', 'KB', 'MB', 'GB'];
|
|
135
|
+
let size = bytes;
|
|
136
|
+
let unitIndex = 0;
|
|
137
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
138
|
+
size /= 1024;
|
|
139
|
+
unitIndex++;
|
|
140
|
+
}
|
|
141
|
+
return `${size.toFixed(2)} ${units[unitIndex]}`;
|
|
142
|
+
}
|