sc-skill 1.0.8 → 1.0.9
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 +26 -0
- package/dist/cli.js +157 -101
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
- 🎯 交互式勾选启用/禁用技能
|
|
9
9
|
- ⚡ 一键开启或关闭全部缓存技能
|
|
10
10
|
- 📋 通过复制方式启用/禁用技能
|
|
11
|
+
- 🚀 快速初始化 SEI 前端项目
|
|
11
12
|
- 📦 支持多平台 (Windows/macOS/Linux)
|
|
12
13
|
|
|
13
14
|
## 安装
|
|
@@ -26,6 +27,18 @@ pnpm build
|
|
|
26
27
|
npm link
|
|
27
28
|
```
|
|
28
29
|
|
|
30
|
+
### 发布到 npmjs
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run adduser:npmjs
|
|
34
|
+
npm run publish:npmjs
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
说明:
|
|
38
|
+
|
|
39
|
+
- npm 官网是 `https://www.npmjs.com`
|
|
40
|
+
- CLI 的 `adduser` 和 `publish` 需要指定 registry,因此这里使用 `https://registry.npmjs.org/`
|
|
41
|
+
|
|
29
42
|
## 使用
|
|
30
43
|
|
|
31
44
|
### 1. 同步技能到缓存
|
|
@@ -68,6 +81,19 @@ sczl list
|
|
|
68
81
|
|
|
69
82
|
显示所有缓存的技能及其启用状态
|
|
70
83
|
|
|
84
|
+
### 6. 初始化 SEI 前端项目
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
seiweb init
|
|
88
|
+
seiweb init demo
|
|
89
|
+
seiweb init my-app
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
会在当前目录下克隆 `https://codeup.aliyun.com/sczlcq/sei-web-base.git`
|
|
93
|
+
|
|
94
|
+
- 不传目录名时,会交互询问目录名
|
|
95
|
+
- 也支持通过 `sczl seiweb init demo` 使用同一能力
|
|
96
|
+
|
|
71
97
|
## 工作原理
|
|
72
98
|
|
|
73
99
|
1. **缓存区**: 技能存储在 `~/.sc/cache`,通过 git 管理
|
package/dist/cli.js
CHANGED
|
@@ -5,117 +5,163 @@ import { GitRepo } from './git.js';
|
|
|
5
5
|
import { SkillManager } from './manager.js';
|
|
6
6
|
import { DEFAULT_CONFIG, getConfigPath } from './config.js';
|
|
7
7
|
import fs from 'fs-extra';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import simpleGit from 'simple-git';
|
|
8
10
|
const program = new Command();
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
11
|
+
const commandName = path.basename(process.argv[1] || 'sczl');
|
|
12
|
+
const SEI_WEB_BASE_REPO = 'https://codeup.aliyun.com/sczlcq/sei-web-base.git';
|
|
13
|
+
if (commandName === 'seiweb') {
|
|
14
|
+
program
|
|
15
|
+
.name('seiweb')
|
|
16
|
+
.description('SEI 前端初始化工具')
|
|
17
|
+
.version('1.0.0');
|
|
18
|
+
registerSeiwebInitCommand(program);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
program
|
|
22
|
+
.name('sczl')
|
|
23
|
+
.description('团队技能同步工具')
|
|
24
|
+
.version('1.0.0');
|
|
25
|
+
program
|
|
26
|
+
.command('sync')
|
|
27
|
+
.description('从团队仓库同步技能')
|
|
28
|
+
.action(async () => {
|
|
29
|
+
try {
|
|
30
|
+
await syncSkills();
|
|
31
|
+
console.log('\n💡 运行 sczl toggle 来启用/禁用技能');
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.error('❌ 同步失败:', error);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
program
|
|
39
|
+
.command('toggle')
|
|
40
|
+
.description('交互式启用/禁用技能')
|
|
41
|
+
.action(async () => {
|
|
42
|
+
try {
|
|
43
|
+
const { manager, available, manageableEnabled } = await loadManageableSkills();
|
|
44
|
+
const answers = await inquirer.prompt([
|
|
45
|
+
{
|
|
46
|
+
type: 'checkbox',
|
|
47
|
+
name: 'skills',
|
|
48
|
+
message: '选择要启用的技能 (空格选择/取消):',
|
|
49
|
+
choices: available.map((skill) => ({
|
|
50
|
+
name: skill,
|
|
51
|
+
checked: manageableEnabled.includes(skill),
|
|
52
|
+
})),
|
|
53
|
+
},
|
|
54
|
+
]);
|
|
55
|
+
const selected = answers.skills;
|
|
56
|
+
const toEnable = selected;
|
|
57
|
+
const toDisable = manageableEnabled.filter((skill) => !selected.includes(skill));
|
|
58
|
+
if (toEnable.length > 0) {
|
|
59
|
+
await manager.enableSkills(toEnable);
|
|
60
|
+
console.log(`✅ 已同步并启用 ${toEnable.length} 个技能`);
|
|
61
|
+
}
|
|
62
|
+
if (toDisable.length > 0) {
|
|
63
|
+
await manager.disableSkills(toDisable);
|
|
64
|
+
console.log(`❌ 已禁用 ${toDisable.length} 个技能`);
|
|
65
|
+
}
|
|
66
|
+
if (toEnable.length === 0 && toDisable.length === 0) {
|
|
67
|
+
console.log('✨ 没有变化');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error('❌ 操作失败:', error);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
program
|
|
76
|
+
.command('open')
|
|
77
|
+
.description('先同步,再启用缓存中的全部技能')
|
|
78
|
+
.action(async () => {
|
|
79
|
+
try {
|
|
80
|
+
await syncSkills();
|
|
81
|
+
const { manager, available } = await loadManageableSkills();
|
|
82
|
+
const toEnable = available;
|
|
83
|
+
if (toEnable.length === 0) {
|
|
84
|
+
console.log('✨ 所有缓存技能已启用');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
47
87
|
await manager.enableSkills(toEnable);
|
|
48
|
-
console.log(`✅
|
|
88
|
+
console.log(`✅ 已同步并覆盖全部技能,共 ${available.length} 个`);
|
|
49
89
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error('❌ 操作失败:', error);
|
|
92
|
+
process.exit(1);
|
|
53
93
|
}
|
|
54
|
-
|
|
55
|
-
|
|
94
|
+
});
|
|
95
|
+
program
|
|
96
|
+
.command('close')
|
|
97
|
+
.description('禁用缓存中的全部技能')
|
|
98
|
+
.action(async () => {
|
|
99
|
+
try {
|
|
100
|
+
const { manager, manageableEnabled } = await loadManageableSkills();
|
|
101
|
+
if (manageableEnabled.length === 0) {
|
|
102
|
+
console.log('✨ 所有缓存技能已禁用');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
await manager.disableSkills(manageableEnabled);
|
|
106
|
+
console.log(`✅ 已禁用全部技能,共 ${manageableEnabled.length} 个`);
|
|
56
107
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
process.exit(1);
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
program
|
|
64
|
-
.command('open')
|
|
65
|
-
.description('先同步,再启用缓存中的全部技能')
|
|
66
|
-
.action(async () => {
|
|
67
|
-
try {
|
|
68
|
-
await syncSkills();
|
|
69
|
-
const { manager, available } = await loadManageableSkills();
|
|
70
|
-
const toEnable = available;
|
|
71
|
-
if (toEnable.length === 0) {
|
|
72
|
-
console.log('✨ 所有缓存技能已启用');
|
|
73
|
-
return;
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error('❌ 操作失败:', error);
|
|
110
|
+
process.exit(1);
|
|
74
111
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
.description('禁用缓存中的全部技能')
|
|
86
|
-
.action(async () => {
|
|
87
|
-
try {
|
|
88
|
-
const { manager, manageableEnabled } = await loadManageableSkills();
|
|
89
|
-
if (manageableEnabled.length === 0) {
|
|
90
|
-
console.log('✨ 所有缓存技能已禁用');
|
|
112
|
+
});
|
|
113
|
+
program
|
|
114
|
+
.command('list')
|
|
115
|
+
.description('列出技能状态')
|
|
116
|
+
.action(async () => {
|
|
117
|
+
const manager = new SkillManager();
|
|
118
|
+
const available = await manager.getAvailableSkills();
|
|
119
|
+
const enabled = await manager.getEnabledSkills();
|
|
120
|
+
if (available.length === 0) {
|
|
121
|
+
console.log('缓存中没有技能,请先运行 sczl sync');
|
|
91
122
|
return;
|
|
92
123
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
program
|
|
102
|
-
.command('list')
|
|
103
|
-
.description('列出技能状态')
|
|
104
|
-
.action(async () => {
|
|
105
|
-
const manager = new SkillManager();
|
|
106
|
-
const available = await manager.getAvailableSkills();
|
|
107
|
-
const enabled = await manager.getEnabledSkills();
|
|
108
|
-
if (available.length === 0) {
|
|
109
|
-
console.log('缓存中没有技能,请先运行 sczl sync');
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
console.log(`\n📦 缓存中的技能 (${available.length}):`);
|
|
113
|
-
available.forEach((skill) => {
|
|
114
|
-
const status = enabled.includes(skill) ? '✅' : '⬜';
|
|
115
|
-
console.log(` ${status} ${skill}`);
|
|
124
|
+
console.log(`\n📦 缓存中的技能 (${available.length}):`);
|
|
125
|
+
available.forEach((skill) => {
|
|
126
|
+
const status = enabled.includes(skill) ? '✅' : '⬜';
|
|
127
|
+
console.log(` ${status} ${skill}`);
|
|
128
|
+
});
|
|
116
129
|
});
|
|
117
|
-
|
|
130
|
+
const seiweb = program.command('seiweb').description('SEI 前端工具');
|
|
131
|
+
registerSeiwebInitCommand(seiweb);
|
|
132
|
+
}
|
|
118
133
|
program.parse();
|
|
134
|
+
function registerSeiwebInitCommand(command) {
|
|
135
|
+
command
|
|
136
|
+
.command('init [directory]')
|
|
137
|
+
.description('初始化 SEI 前端项目,不传目录名时会交互询问')
|
|
138
|
+
.action(async (directory) => {
|
|
139
|
+
try {
|
|
140
|
+
const targetDirectory = directory || (await promptSeiWebDirectory());
|
|
141
|
+
await initSeiWebProject(targetDirectory);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error('❌ 初始化失败:', error);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
async function promptSeiWebDirectory() {
|
|
150
|
+
const answers = await inquirer.prompt([
|
|
151
|
+
{
|
|
152
|
+
type: 'input',
|
|
153
|
+
name: 'directory',
|
|
154
|
+
message: '请输入项目目录名:',
|
|
155
|
+
validate: (value) => {
|
|
156
|
+
if (!value || !value.trim()) {
|
|
157
|
+
return '目录名不能为空';
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
]);
|
|
163
|
+
return answers.directory.trim();
|
|
164
|
+
}
|
|
119
165
|
async function loadConfig() {
|
|
120
166
|
const configPath = getConfigPath();
|
|
121
167
|
if (await fs.pathExists(configPath)) {
|
|
@@ -154,3 +200,13 @@ async function loadManageableSkills() {
|
|
|
154
200
|
manageableEnabled,
|
|
155
201
|
};
|
|
156
202
|
}
|
|
203
|
+
async function initSeiWebProject(directory) {
|
|
204
|
+
const normalizedDirectory = directory.trim();
|
|
205
|
+
const targetDir = path.resolve(process.cwd(), normalizedDirectory);
|
|
206
|
+
if (await fs.pathExists(targetDir)) {
|
|
207
|
+
throw new Error(`目录已存在: ${targetDir}`);
|
|
208
|
+
}
|
|
209
|
+
console.log(`🔄 正在初始化 SEI 前端项目: ${normalizedDirectory}`);
|
|
210
|
+
await simpleGit().clone(SEI_WEB_BASE_REPO, targetDir);
|
|
211
|
+
console.log(`✅ 初始化完成: ${targetDir}`);
|
|
212
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sc-skill",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "团队技能同步工具",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"sczl": "./dist/cli.js"
|
|
8
|
+
"sczl": "./dist/cli.js",
|
|
9
|
+
"seiweb": "./dist/cli.js"
|
|
9
10
|
},
|
|
10
11
|
"files": [
|
|
11
12
|
"dist",
|
|
@@ -15,7 +16,9 @@
|
|
|
15
16
|
"build": "tsc",
|
|
16
17
|
"dev": "tsc --watch",
|
|
17
18
|
"start": "node dist/cli.js",
|
|
18
|
-
"prepublishOnly": "pnpm run build"
|
|
19
|
+
"prepublishOnly": "pnpm run build",
|
|
20
|
+
"adduser:npmjs": "npm adduser --registry https://registry.npmjs.org/",
|
|
21
|
+
"publish:npmjs": "npm publish --registry https://registry.npmjs.org/"
|
|
19
22
|
},
|
|
20
23
|
"keywords": [
|
|
21
24
|
"claude",
|