dk-frontend-skills 2.1.2 → 2.1.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.
- package/package.json +1 -1
- package/scripts/cli.js +38 -11
- package/scripts/copy-skills.js +9 -3
- package/scripts/core.js +21 -4
package/package.json
CHANGED
package/scripts/cli.js
CHANGED
|
@@ -23,7 +23,8 @@ const pkgSkillsSource = path.join(packageDir, ".claude", "skills");
|
|
|
23
23
|
// ---------- 文件写入 ----------
|
|
24
24
|
|
|
25
25
|
function readSettings() {
|
|
26
|
-
if (!fs.existsSync(settingsPath))
|
|
26
|
+
if (!fs.existsSync(settingsPath))
|
|
27
|
+
return { skills: {}, always_apply_skills: [] };
|
|
27
28
|
try {
|
|
28
29
|
return JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
29
30
|
} catch {
|
|
@@ -35,11 +36,29 @@ function writeSettings(settings) {
|
|
|
35
36
|
if (!fs.existsSync(claudeDest)) {
|
|
36
37
|
fs.mkdirSync(claudeDest, { recursive: true });
|
|
37
38
|
}
|
|
38
|
-
fs.writeFileSync(
|
|
39
|
+
fs.writeFileSync(
|
|
40
|
+
settingsPath,
|
|
41
|
+
JSON.stringify(settings, null, 2) + "\n",
|
|
42
|
+
"utf-8",
|
|
43
|
+
);
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
// ---------- 安装勾选的技能 ----------
|
|
42
47
|
|
|
48
|
+
// 手动递归拷贝目录,绕开 Windows 中文路径下 fs.cpSync({ recursive: true }) 死锁的 bug
|
|
49
|
+
function copyDirSync(src, dest) {
|
|
50
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
51
|
+
for (const item of fs.readdirSync(src)) {
|
|
52
|
+
const srcPath = path.join(src, item);
|
|
53
|
+
const destPath = path.join(dest, item);
|
|
54
|
+
if (fs.statSync(srcPath).isDirectory()) {
|
|
55
|
+
copyDirSync(srcPath, destPath);
|
|
56
|
+
} else {
|
|
57
|
+
fs.copyFileSync(srcPath, destPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
43
62
|
function installSelectedSkills(selectedNames) {
|
|
44
63
|
// 创建 .claude/ 和 skills/ 目录
|
|
45
64
|
if (!fs.existsSync(skillsDest)) {
|
|
@@ -57,7 +76,7 @@ function installSelectedSkills(selectedNames) {
|
|
|
57
76
|
// 勾选了的 → 安装(不存在才装)
|
|
58
77
|
if (!fs.existsSync(dest)) {
|
|
59
78
|
try {
|
|
60
|
-
|
|
79
|
+
copyDirSync(src, dest);
|
|
61
80
|
installedCount++;
|
|
62
81
|
} catch (err) {
|
|
63
82
|
console.error(` ❌ 安装技能 "${name}" 失败:`, err.message);
|
|
@@ -119,13 +138,15 @@ async function cmdList() {
|
|
|
119
138
|
const allSkills = [...skillMap.values()];
|
|
120
139
|
|
|
121
140
|
console.log(`\n${chalk.bold("📋 dk-frontend-skills 技能清单")}\n`);
|
|
122
|
-
console.log(
|
|
123
|
-
|
|
141
|
+
console.log(
|
|
142
|
+
` ${chalk.dim("状态 技能名 版本 描述")}`,
|
|
143
|
+
);
|
|
144
|
+
console.log(
|
|
145
|
+
` ${chalk.dim("─────────────────────────────────────────────────────")}`,
|
|
146
|
+
);
|
|
124
147
|
|
|
125
148
|
for (const skill of allSkills) {
|
|
126
|
-
const status = skill.enabled
|
|
127
|
-
? chalk.green("● 启用")
|
|
128
|
-
: chalk.gray("○ 停用");
|
|
149
|
+
const status = skill.enabled ? chalk.green("● 启用") : chalk.gray("○ 停用");
|
|
129
150
|
const name = chalk.white(skill.name.padEnd(20));
|
|
130
151
|
const ver = chalk.dim(skill.version.padEnd(7));
|
|
131
152
|
const desc = skill.description
|
|
@@ -134,7 +155,9 @@ async function cmdList() {
|
|
|
134
155
|
console.log(` ${status} ${name} ${ver} ${desc}`);
|
|
135
156
|
}
|
|
136
157
|
|
|
137
|
-
console.log(
|
|
158
|
+
console.log(
|
|
159
|
+
`\n ${chalk.cyan("💡")} ${chalk.dim("运行 npx dk-frontend-skills 进入交互选择模式")}\n`,
|
|
160
|
+
);
|
|
138
161
|
}
|
|
139
162
|
|
|
140
163
|
// ---------- 交互式菜单(选完即装) ----------
|
|
@@ -183,7 +206,9 @@ async function startInteractiveMenu() {
|
|
|
183
206
|
});
|
|
184
207
|
|
|
185
208
|
const newCount = selected.filter((name) => !installedSet.has(name)).length;
|
|
186
|
-
const removedCount = [...installedSet].filter(
|
|
209
|
+
const removedCount = [...installedSet].filter(
|
|
210
|
+
(name) => !selected.includes(name),
|
|
211
|
+
).length;
|
|
187
212
|
|
|
188
213
|
const installed = installSelectedSkills(selected);
|
|
189
214
|
|
|
@@ -223,7 +248,9 @@ async function main() {
|
|
|
223
248
|
} else if (command === "list") {
|
|
224
249
|
await cmdList();
|
|
225
250
|
} else if (command === "enable" || command === "disable") {
|
|
226
|
-
console.log(
|
|
251
|
+
console.log(
|
|
252
|
+
` ⚠️ 该命令已废弃,请直接运行 npx dk-frontend-skills 使用交互菜单\n`,
|
|
253
|
+
);
|
|
227
254
|
} else {
|
|
228
255
|
console.log(` 未知命令: ${command}\n 可用: ${COMMANDS.join(", ")}\n`);
|
|
229
256
|
process.exit(1);
|
package/scripts/copy-skills.js
CHANGED
|
@@ -4,13 +4,15 @@ const {
|
|
|
4
4
|
backupTimestamp,
|
|
5
5
|
appendLog,
|
|
6
6
|
backupDir,
|
|
7
|
+
copyDirSync,
|
|
7
8
|
installSkills,
|
|
8
9
|
installSettings,
|
|
9
10
|
} = require("./core");
|
|
10
11
|
|
|
11
12
|
// 获取用户项目根目录
|
|
12
13
|
// npm lifecycle 脚本会设置 INIT_CWD 为执行命令时的目录,比从 __dirname 爬三级更可靠
|
|
13
|
-
const projectRoot =
|
|
14
|
+
const projectRoot =
|
|
15
|
+
process.env.INIT_CWD || path.resolve(__dirname, "..", "..", "..");
|
|
14
16
|
const packageDir = path.join(__dirname, "..");
|
|
15
17
|
|
|
16
18
|
// 源路径
|
|
@@ -42,7 +44,7 @@ if (fs.existsSync(claudeSource)) {
|
|
|
42
44
|
} else {
|
|
43
45
|
// 全新安装
|
|
44
46
|
appendLog(logFile, "INFO", "Install started (fresh)");
|
|
45
|
-
|
|
47
|
+
copyDirSync(claudeSource, claudeDest);
|
|
46
48
|
appendLog(logFile, "INFO", `.claude/ directory created`);
|
|
47
49
|
}
|
|
48
50
|
}
|
|
@@ -60,7 +62,11 @@ if (fs.existsSync(mdSource)) {
|
|
|
60
62
|
const bakName = `CLAUDE.md.${backupTimestamp()}`;
|
|
61
63
|
const bakPath = path.join(backupsDir, bakName);
|
|
62
64
|
fs.copyFileSync(mdDest, bakPath);
|
|
63
|
-
appendLog(
|
|
65
|
+
appendLog(
|
|
66
|
+
logFile,
|
|
67
|
+
"BACKUP",
|
|
68
|
+
`backups/${bakName} (CLAUDE.md user version preserved)`,
|
|
69
|
+
);
|
|
64
70
|
}
|
|
65
71
|
}
|
|
66
72
|
|
package/scripts/core.js
CHANGED
|
@@ -46,7 +46,7 @@ function backupDir(dir) {
|
|
|
46
46
|
|
|
47
47
|
for (const item of fs.readdirSync(dir)) {
|
|
48
48
|
if (item === "backups") continue;
|
|
49
|
-
|
|
49
|
+
copyDirSync(path.join(dir, item), path.join(bakPath, item));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// 清理旧备份,只保留最近 3 份
|
|
@@ -70,6 +70,22 @@ function isPlainObject(val) {
|
|
|
70
70
|
return Object.prototype.toString.call(val) === "[object Object]";
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* 手动递归拷贝目录,绕开 Windows 中文路径下 fs.cpSync({ recursive: true }) 死锁的 bug
|
|
75
|
+
*/
|
|
76
|
+
function copyDirSync(src, dest) {
|
|
77
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
78
|
+
for (const item of fs.readdirSync(src)) {
|
|
79
|
+
const srcPath = path.join(src, item);
|
|
80
|
+
const destPath = path.join(dest, item);
|
|
81
|
+
if (fs.statSync(srcPath).isDirectory()) {
|
|
82
|
+
copyDirSync(srcPath, destPath);
|
|
83
|
+
} else {
|
|
84
|
+
fs.copyFileSync(srcPath, destPath);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
73
89
|
/**
|
|
74
90
|
* 递归深合并,用户值优先,目标新增字段补充
|
|
75
91
|
*/
|
|
@@ -122,7 +138,7 @@ function installSkills(skillsSource, skillsDest, logFile) {
|
|
|
122
138
|
const version = meta ? meta.version : "?";
|
|
123
139
|
|
|
124
140
|
if (!fs.existsSync(destSkill)) {
|
|
125
|
-
|
|
141
|
+
copyDirSync(srcSkill, destSkill);
|
|
126
142
|
appendLog(logFile, "SKILL", `${dir} (${version}) → installed`);
|
|
127
143
|
results.push({ name: dir, version, action: "installed" });
|
|
128
144
|
} else {
|
|
@@ -132,9 +148,9 @@ function installSkills(skillsSource, skillsDest, logFile) {
|
|
|
132
148
|
if (needUpdate) {
|
|
133
149
|
const bakName = `${dir}.bak.${backupTimestamp()}`;
|
|
134
150
|
const bakPath = path.join(skillsDest, bakName);
|
|
135
|
-
|
|
151
|
+
copyDirSync(destSkill, bakPath);
|
|
136
152
|
fs.rmSync(destSkill, { recursive: true, force: true });
|
|
137
|
-
|
|
153
|
+
copyDirSync(srcSkill, destSkill);
|
|
138
154
|
appendLog(logFile, "SKILL", `${dir} (${destMeta.version} → ${meta.version}) → updated`);
|
|
139
155
|
results.push({ name: dir, version: meta.version, action: "updated" });
|
|
140
156
|
} else {
|
|
@@ -230,6 +246,7 @@ module.exports = {
|
|
|
230
246
|
backupTimestamp,
|
|
231
247
|
appendLog,
|
|
232
248
|
backupDir,
|
|
249
|
+
copyDirSync,
|
|
233
250
|
deepMerge,
|
|
234
251
|
readMeta,
|
|
235
252
|
installSkills,
|