@gmcb/cli 0.3.3 → 0.4.0

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/CHANGELOG.md CHANGED
@@ -1,43 +1,52 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
- See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
-
6
- ## [0.3.3](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.3.2...@gmcb/cli@0.3.3) (2026-04-24)
7
-
8
- **Note:** Version bump only for package @gmcb/cli
9
-
10
-
11
-
12
-
13
-
14
- ## [0.3.2](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.3.1...@gmcb/cli@0.3.2) (2026-04-22)
15
-
16
- **Note:** Version bump only for package @gmcb/cli
17
-
18
-
19
-
20
-
21
-
22
- ## [0.3.1](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.3.0...@gmcb/cli@0.3.1) (2026-04-22)
23
-
24
- **Note:** Version bump only for package @gmcb/cli
25
-
26
-
27
-
28
-
29
-
30
- # [0.3.0](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.2.4...@gmcb/cli@0.3.0) (2026-04-22)
31
-
32
-
33
- ### Features
34
-
35
- * 优化使用体验 ([c82d28b](http://10.10.10.16/caoben/front-end/commits/c82d28ba920f857e5edc4865a7a88030b32230c1))
36
-
37
-
38
-
39
-
40
-
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [0.3.4](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.3.3...@gmcb/cli@0.3.4) (2026-04-30)
7
+
8
+ **Note:** Version bump only for package @gmcb/cli
9
+
10
+
11
+
12
+
13
+
14
+
15
+ ## [0.3.3](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.3.2...@gmcb/cli@0.3.3) (2026-04-24)
16
+
17
+ **Note:** Version bump only for package @gmcb/cli
18
+
19
+
20
+
21
+
22
+
23
+ ## [0.3.2](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.3.1...@gmcb/cli@0.3.2) (2026-04-22)
24
+
25
+ **Note:** Version bump only for package @gmcb/cli
26
+
27
+
28
+
29
+
30
+
31
+ ## [0.3.1](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.3.0...@gmcb/cli@0.3.1) (2026-04-22)
32
+
33
+ **Note:** Version bump only for package @gmcb/cli
34
+
35
+
36
+
37
+
38
+
39
+ # [0.3.0](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.2.4...@gmcb/cli@0.3.0) (2026-04-22)
40
+
41
+
42
+ ### Features
43
+
44
+ * 优化使用体验 ([c82d28b](http://10.10.10.16/caoben/front-end/commits/c82d28ba920f857e5edc4865a7a88030b32230c1))
45
+
46
+
47
+
48
+
49
+
41
50
 
42
51
  ## [0.2.4](http://10.10.10.16/caoben/front-end/compare/@gmcb/cli@0.2.3...@gmcb/cli@0.2.4) (2025-11-13)
43
52
 
@@ -279,4 +288,4 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
279
288
 
280
289
  ## [0.0.1](http://10.10.200.92:8090/gmcb/front-end/compare/@gmcb/cli@0.1.0-alpha.0...@gmcb/cli@0.0.1) (2025-02-02)
281
290
 
282
- **Note:** Version bump only for package @gmcb/cli
291
+ **Note:** Version bump only for package @gmcb/cli
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 aniu
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 CHANGED
@@ -9,6 +9,36 @@ npm i @gmcb/cli -g
9
9
  ```
10
10
 
11
11
  ## 使用
12
+
13
+ ### 构建
14
+
12
15
  ```
13
16
  gmcb build
17
+ ```
18
+
19
+ ### 技能管理
20
+
21
+ 从远程仓库同步技能到本地项目:
22
+
23
+ ```
24
+ gmcb skill sync
25
+ ```
26
+
27
+ 可选参数:
28
+ - `--skill.repo <repo-url>` - 指定技能仓库 Git 地址,覆盖默认配置
29
+
30
+ 列出当前项目所有技能:
31
+
32
+ ```
33
+ gmcb skill list
34
+ ```
35
+
36
+ 技能仓库地址可在 `uni.build.json` 中配置:
37
+
38
+ ```json
39
+ {
40
+ "skill": {
41
+ "repo": "http://10.10.10.16/caoben/skill.git"
42
+ }
43
+ }
14
44
  ```
@@ -152,7 +152,12 @@ async function getCommands(...args) {
152
152
  }
153
153
  }
154
154
  else if (opts.compiler === 'electron-vite') {
155
- commands = [...commands, bin, 'build', `&& cross-env CHANNEL=-${buildEnv}`];
155
+ commands = [
156
+ ...commands,
157
+ bin,
158
+ 'build',
159
+ `&& cross-env CHANNEL=${String(buildEnv).startsWith('pro') ? '' : `-${buildEnv}`}`,
160
+ ];
156
161
  if (opts.zip) {
157
162
  commands.push('electron-builder --dir');
158
163
  }
@@ -42,6 +42,12 @@ interface Mp {
42
42
  privatekey?: string;
43
43
  };
44
44
  }
45
+ interface Skill {
46
+ repo?: string;
47
+ }
48
+ interface Template {
49
+ repo?: string;
50
+ }
45
51
  interface Publish {
46
52
  brand: string;
47
53
  type: string;
@@ -56,6 +62,8 @@ export interface BaseConfig {
56
62
  branch?: string | boolean;
57
63
  cos?: Cos;
58
64
  cli?: Cli;
65
+ skill?: Skill;
66
+ template?: Template;
59
67
  }
60
68
  export interface Config extends BaseConfig {
61
69
  env?: string;
@@ -24,6 +24,12 @@ function getConfig() {
24
24
  cli: {
25
25
  hbuilderx,
26
26
  },
27
+ skill: {
28
+ repo: utils_1.DEFAULT_SKILL_REPO,
29
+ },
30
+ template: {
31
+ repo: utils_1.DEFAULT_TEMPLATE_REPO,
32
+ },
27
33
  }, { spaces: 2 });
28
34
  }
29
35
  return (0, fs_extra_1.readJsonSync)(utils_1.CONFIG_PATH, { throws: false }) || {};
@@ -1,66 +1,122 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
29
  exports.default = default_1;
7
30
  const path_1 = require("path");
31
+ const fs_1 = require("fs");
8
32
  const inquirer_1 = __importDefault(require("inquirer"));
9
- const download_1 = __importDefault(require("download"));
33
+ const simple_git_1 = __importDefault(require("simple-git"));
10
34
  const ora_1 = __importDefault(require("ora"));
11
35
  const chalk_1 = __importDefault(require("chalk"));
36
+ const fsExtra = __importStar(require("fs-extra"));
37
+ const os_1 = __importDefault(require("os"));
12
38
  const utils_1 = require("../utils");
13
- function downloadTemplate(name, dest) {
14
- if (!/https?:/.test(name)) {
15
- name = `https://git.keeprisk.cn/${name}`;
16
- }
17
- const [url, branch = 'master'] = name.split('#');
18
- const array = url.replace(/\/+$/, '').split('/');
19
- const repoName = array.pop();
20
- return (0, download_1.default)(`${url}/-/archive/${branch}/${repoName}-${branch}.zip`, dest, { extract: true, strip: 1 });
21
- }
39
+ const config_1 = require("./config");
22
40
  async function default_1(...args) {
23
41
  const name = args[0];
24
- const opts = args[2];
42
+ const opts = args[1];
25
43
  const dest = (0, path_1.join)(utils_1.COMMAND_PATH, name);
44
+ const config = (0, config_1.getMergeConfig)();
45
+ const repoUrl = opts['template.repo'] || config.template?.repo || utils_1.DEFAULT_TEMPLATE_REPO;
46
+ const tempDir = (0, path_1.join)(os_1.default.tmpdir(), `gmcb-template-${Date.now()}`);
47
+ const spinner = (0, ora_1.default)('正在克隆模板仓库...');
48
+ try {
49
+ spinner.start();
50
+ await (0, simple_git_1.default)().clone(repoUrl, tempDir, ['--depth', '1']);
51
+ spinner.succeed('模板仓库克隆完成');
52
+ }
53
+ catch (e) {
54
+ spinner.fail('克隆模板仓库失败:' + e.message);
55
+ return;
56
+ }
57
+ const packagesDir = (0, path_1.join)(tempDir, 'packages');
58
+ if (!(0, fs_1.existsSync)(packagesDir)) {
59
+ utils_1.log.error('模板仓库中未发现 packages 目录');
60
+ await fsExtra.remove(tempDir);
61
+ return;
62
+ }
63
+ const templates = (0, fs_1.readdirSync)(packagesDir).filter((item) => {
64
+ return (0, fs_1.existsSync)((0, path_1.join)(packagesDir, item));
65
+ });
66
+ if (templates.length === 0) {
67
+ utils_1.log.error('模板仓库 packages 目录为空,未发现任何模板');
68
+ await fsExtra.remove(tempDir);
69
+ return;
70
+ }
26
71
  let { template } = opts;
27
72
  if (!template) {
28
- template = 'project-template/uniapp';
29
- const res = await inquirer_1.default.prompt([
30
- {
31
- type: 'list',
32
- name: 'template',
33
- message: '请选择模版类型',
34
- choices: [
35
- {
36
- name: 'JS模版',
37
- value: '',
38
- },
39
- {
40
- name: 'TS模版',
41
- value: '-ts',
42
- },
43
- ],
44
- },
45
- ]);
46
- template += res.template;
73
+ if (templates.length === 1) {
74
+ template = templates[0];
75
+ console.log(chalk_1.default.cyan(`使用模板: ${template}`));
76
+ }
77
+ else {
78
+ const ans = await inquirer_1.default.prompt([
79
+ {
80
+ type: 'list',
81
+ name: 'template',
82
+ message: '请选择模板类型',
83
+ choices: templates.map((t) => ({ name: t, value: t })),
84
+ },
85
+ ]);
86
+ template = ans.template;
87
+ }
47
88
  }
48
- const spinner = (0, ora_1.default)('模版下载中...');
89
+ else {
90
+ if (!templates.includes(template)) {
91
+ utils_1.log.error(`模板 "${template}" 不存在,可用模板:${templates.join(', ')}`);
92
+ await fsExtra.remove(tempDir);
93
+ return;
94
+ }
95
+ }
96
+ const templatePath = (0, path_1.join)(packagesDir, template);
97
+ const copySpinner = (0, ora_1.default)('正在创建项目...');
49
98
  try {
50
- spinner.start();
51
- await downloadTemplate(template, dest);
52
- spinner.succeed('模版已下载,请执行以下命令:');
99
+ copySpinner.start();
100
+ await fsExtra.copy(templatePath, dest);
101
+ const pkgPath = (0, path_1.join)(dest, 'package.json');
102
+ if ((0, fs_1.existsSync)(pkgPath)) {
103
+ const pkg = await fsExtra.readJson(pkgPath);
104
+ pkg.name = name;
105
+ await fsExtra.writeJson(pkgPath, pkg, { spaces: 2 });
106
+ }
107
+ copySpinner.succeed('项目创建完成,请执行以下命令:');
53
108
  const rela = (0, path_1.relative)(utils_1.COMMAND_PATH, dest);
54
109
  if (rela) {
55
110
  console.log(chalk_1.default.blueBright(`$ cd ${rela}`));
56
111
  }
57
- console.log(chalk_1.default.blueBright('$ nrm use coding'));
58
- console.log(chalk_1.default.blueBright('$ npm i'));
112
+ console.log(chalk_1.default.blueBright('$ gmcb skill sync'));
113
+ console.log(chalk_1.default.blueBright('$ npm install'));
59
114
  }
60
115
  catch (e) {
61
- spinner.fail('模版已下载失败:' + e.message);
116
+ copySpinner.fail('项目创建失败:' + e.message);
62
117
  }
63
118
  finally {
64
- spinner.stop();
119
+ await fsExtra.remove(tempDir);
120
+ copySpinner.stop();
65
121
  }
66
122
  }
@@ -0,0 +1,2 @@
1
+ export declare function syncSkill(...args: any[]): Promise<void>;
2
+ export declare function listSkill(): Promise<void>;
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.syncSkill = syncSkill;
30
+ exports.listSkill = listSkill;
31
+ const path_1 = require("path");
32
+ const fs_1 = require("fs");
33
+ const fs_2 = require("fs");
34
+ const simple_git_1 = __importDefault(require("simple-git"));
35
+ const inquirer_1 = __importDefault(require("inquirer"));
36
+ const ora_1 = __importDefault(require("ora"));
37
+ const chalk_1 = __importDefault(require("chalk"));
38
+ const fsExtra = __importStar(require("fs-extra"));
39
+ const os_1 = __importDefault(require("os"));
40
+ const config_1 = require("./config");
41
+ const utils_1 = require("../utils");
42
+ const ENV_MAP = {
43
+ default: ".agents",
44
+ opencode: ".opencode",
45
+ claude: ".claude",
46
+ codex: ".codex",
47
+ qoder: ".qoder",
48
+ };
49
+ function parseFrontmatter(content) {
50
+ const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
51
+ if (!match)
52
+ return {};
53
+ const frontmatter = match[1];
54
+ const result = {};
55
+ frontmatter.split("\n").forEach((line) => {
56
+ const colonIndex = line.indexOf(":");
57
+ if (colonIndex !== -1) {
58
+ const key = line.substring(0, colonIndex).trim();
59
+ const value = line.substring(colonIndex + 1).trim();
60
+ result[key] = value;
61
+ }
62
+ });
63
+ return { name: result.name, description: result.description };
64
+ }
65
+ function getExistingEnvs() {
66
+ const result = [];
67
+ Object.keys(ENV_MAP).forEach((env) => {
68
+ if ((0, fs_1.existsSync)((0, path_1.join)(utils_1.COMMAND_PATH, ENV_MAP[env]))) {
69
+ result.push(env);
70
+ }
71
+ });
72
+ return result;
73
+ }
74
+ function scanLocalSkills(envDir) {
75
+ const skillsPath = (0, path_1.join)(envDir, "skills");
76
+ if (!(0, fs_1.existsSync)(skillsPath))
77
+ return [];
78
+ return (0, fs_1.readdirSync)(skillsPath).filter((name) => {
79
+ const skillMd = (0, path_1.join)(skillsPath, name, "SKILL.md");
80
+ return (0, fs_1.existsSync)(skillMd);
81
+ });
82
+ }
83
+ function scanRemoteSkills(repoDir) {
84
+ const skills = [];
85
+ const skillsDir = (0, fs_1.existsSync)((0, path_1.join)(repoDir, "skills")) ? (0, path_1.join)(repoDir, "skills") : repoDir;
86
+ const items = (0, fs_1.readdirSync)(skillsDir);
87
+ items.forEach((item) => {
88
+ const itemPath = (0, path_1.join)(skillsDir, item);
89
+ const skillMd = (0, path_1.join)(itemPath, "SKILL.md");
90
+ if ((0, fs_1.existsSync)(skillMd)) {
91
+ const content = (0, fs_2.readFileSync)(skillMd, "utf-8");
92
+ const { name, description } = parseFrontmatter(content);
93
+ skills.push({
94
+ name: name || item,
95
+ description: description || "",
96
+ path: itemPath,
97
+ });
98
+ }
99
+ });
100
+ return skills;
101
+ }
102
+ async function syncSkill(...args) {
103
+ const opts = args[0];
104
+ const config = (0, config_1.getMergeConfig)();
105
+ const repoUrl = opts["skill.repo"] || config.skill?.repo || utils_1.DEFAULT_SKILL_REPO;
106
+ const tempDir = (0, path_1.join)(os_1.default.tmpdir(), `gmcb-skill-${Date.now()}`);
107
+ const spinner = (0, ora_1.default)("正在克隆技能仓库...");
108
+ try {
109
+ spinner.start();
110
+ await (0, simple_git_1.default)().clone(repoUrl, tempDir);
111
+ spinner.succeed("技能仓库克隆完成");
112
+ }
113
+ catch (e) {
114
+ spinner.fail("克隆技能仓库失败:" + e.message);
115
+ return;
116
+ }
117
+ const remoteSkills = scanRemoteSkills(tempDir);
118
+ if (remoteSkills.length === 0) {
119
+ utils_1.log.warning("远程仓库中未发现任何技能");
120
+ await fsExtra.remove(tempDir);
121
+ return;
122
+ }
123
+ const existingEnvs = getExistingEnvs();
124
+ let selectedEnv;
125
+ if (existingEnvs.length === 1) {
126
+ selectedEnv = existingEnvs[0];
127
+ console.log(chalk_1.default.cyan(`使用已有环境: ${selectedEnv}`));
128
+ }
129
+ else if (existingEnvs.length === 0) {
130
+ const envChoices = Object.keys(ENV_MAP).map((env) => ({
131
+ name: env,
132
+ value: env,
133
+ }));
134
+ const ans = await inquirer_1.default.prompt([
135
+ {
136
+ type: "list",
137
+ name: "env",
138
+ message: "请选择目标环境",
139
+ choices: envChoices,
140
+ default: "default",
141
+ },
142
+ ]);
143
+ selectedEnv = ans.env;
144
+ }
145
+ else {
146
+ const envChoices = existingEnvs.map((env) => ({
147
+ name: env,
148
+ value: env,
149
+ }));
150
+ const ans = await inquirer_1.default.prompt([
151
+ {
152
+ type: "list",
153
+ name: "env",
154
+ message: "检测到多个环境,请选择",
155
+ choices: envChoices,
156
+ default: existingEnvs[0],
157
+ },
158
+ ]);
159
+ selectedEnv = ans.env;
160
+ }
161
+ const targetEnvDir = (0, path_1.join)(utils_1.COMMAND_PATH, ENV_MAP[selectedEnv]);
162
+ const localSkills = scanLocalSkills(targetEnvDir);
163
+ const skillChoices = remoteSkills.map((skill) => ({
164
+ name: `${skill.name} ${skill.description ? `- ${skill.description}` : ""}`,
165
+ value: skill.name,
166
+ checked: localSkills.includes(skill.name),
167
+ }));
168
+ const { selectedSkills } = await inquirer_1.default.prompt([
169
+ {
170
+ type: "checkbox",
171
+ name: "selectedSkills",
172
+ message: "请选择要同步的技能",
173
+ choices: skillChoices,
174
+ },
175
+ ]);
176
+ if (selectedSkills.length === 0) {
177
+ utils_1.log.warning("未选择任何技能");
178
+ await fsExtra.remove(tempDir);
179
+ return;
180
+ }
181
+ const skillsDir = (0, path_1.join)(targetEnvDir, "skills");
182
+ await fsExtra.ensureDir(skillsDir);
183
+ let count = 0;
184
+ for (const skillName of selectedSkills) {
185
+ const remoteSkill = remoteSkills.find((s) => s.name === skillName);
186
+ if (remoteSkill) {
187
+ const destPath = (0, path_1.join)(skillsDir, skillName);
188
+ await fsExtra.copy(remoteSkill.path, destPath, { overwrite: true });
189
+ count++;
190
+ }
191
+ }
192
+ await fsExtra.remove(tempDir);
193
+ utils_1.log.success(`成功同步 ${count} 个技能到 ${ENV_MAP[selectedEnv]} 目录`);
194
+ }
195
+ async function listSkill() {
196
+ let hasSkills = false;
197
+ Object.keys(ENV_MAP).forEach((env) => {
198
+ const envDir = (0, path_1.join)(utils_1.COMMAND_PATH, ENV_MAP[env]);
199
+ const skillsPath = (0, path_1.join)(envDir, "skills");
200
+ if (!(0, fs_1.existsSync)(skillsPath))
201
+ return;
202
+ const skills = (0, fs_1.readdirSync)(skillsPath).filter((name) => {
203
+ return (0, fs_1.existsSync)((0, path_1.join)(skillsPath, name, "SKILL.md"));
204
+ });
205
+ if (skills.length === 0)
206
+ return;
207
+ hasSkills = true;
208
+ console.log(chalk_1.default.cyan(`\n${env} (${ENV_MAP[env]}/skills):`));
209
+ skills.forEach((skillName) => {
210
+ const skillMd = (0, path_1.join)(skillsPath, skillName, "SKILL.md");
211
+ const content = (0, fs_2.readFileSync)(skillMd, "utf-8");
212
+ const { description } = parseFrontmatter(content);
213
+ const desc = description ? ` - ${description}` : "";
214
+ console.log(` ${chalk_1.default.green("●")} ${skillName}${desc}`);
215
+ });
216
+ });
217
+ if (!hasSkills) {
218
+ utils_1.log.warning("当前项目未安装任何技能");
219
+ }
220
+ }
package/lib/bin.js CHANGED
@@ -12,6 +12,7 @@ const build_1 = __importDefault(require("./actions/build"));
12
12
  const publish_1 = __importDefault(require("./actions/publish"));
13
13
  const config_1 = __importDefault(require("./actions/config"));
14
14
  const copy_1 = __importDefault(require("./actions/copy"));
15
+ const skill_1 = require("./actions/skill");
15
16
  const commands_1 = require("./commands");
16
17
  const utils_1 = require("./utils");
17
18
  const program = new commander_1.default.Command();
@@ -23,6 +24,7 @@ program
23
24
  .command('create <project-name>')
24
25
  .description('创建项目框架')
25
26
  .option(...commands_1.template)
27
+ .option(...commands_1.templateRepo)
26
28
  .action(create_1.default);
27
29
  program
28
30
  .command('dev')
@@ -82,4 +84,14 @@ program
82
84
  .option(...commands_1.cosSecretkey)
83
85
  .option(...commands_1.branch)
84
86
  .action(config_1.default);
87
+ const skillCmd = program.command('skill').description('技能管理');
88
+ skillCmd
89
+ .command('sync')
90
+ .description('从远程仓库同步技能到本地项目')
91
+ .option(...commands_1.skillRepo)
92
+ .action(skill_1.syncSkill);
93
+ skillCmd
94
+ .command('list')
95
+ .description('列出当前项目所有技能')
96
+ .action(skill_1.listSkill);
85
97
  program.parse();
@@ -25,6 +25,8 @@ export declare const weixinCli: readonly ["--cli.weixin <cli-path>", "微信开
25
25
  export declare const alipayCli: readonly ["--cli.alipay <cli-path>", "支付宝开发者工具 Cli路径"];
26
26
  export declare const cosSecretid: readonly ["--cos.secretid <secretid>", "设置腾讯云上传秘钥ID"];
27
27
  export declare const cosSecretkey: readonly ["--cos.secretkey <secretkey>", "设置腾讯云上传秘钥KEY"];
28
+ export declare const skillRepo: readonly ["--skill.repo <repo-url>", "技能仓库 Git 地址"];
29
+ export declare const templateRepo: readonly ["--template.repo <repo-url>", "项目模板仓库 Git 地址"];
28
30
  export interface Options {
29
31
  template?: string;
30
32
  branch?: string | boolean;
@@ -46,4 +48,6 @@ export interface Options {
46
48
  win: boolean;
47
49
  mac: boolean;
48
50
  linux: boolean;
51
+ 'skill.repo'?: string;
52
+ 'template.repo'?: string;
49
53
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.cosSecretkey = exports.cosSecretid = exports.alipayCli = exports.weixinCli = exports.hbuilderxCli = exports.res = exports.wgt = exports.custom = exports.zip = exports.linux = exports.mac = exports.win = exports.link = exports.path = exports.name = exports.clean = exports.ignore = exports.dest = exports.source = exports.branch = exports.env = exports.compiler = exports.project = exports.platform = exports.template = exports.version = void 0;
3
+ exports.templateRepo = exports.skillRepo = exports.cosSecretkey = exports.cosSecretid = exports.alipayCli = exports.weixinCli = exports.hbuilderxCli = exports.res = exports.wgt = exports.custom = exports.zip = exports.linux = exports.mac = exports.win = exports.link = exports.path = exports.name = exports.clean = exports.ignore = exports.dest = exports.source = exports.branch = exports.env = exports.compiler = exports.project = exports.platform = exports.template = exports.version = void 0;
4
4
  exports.version = ['-v, --version', '输出版本号'];
5
5
  exports.template = ['-t, --template <template-name>', '模版仓库名称'];
6
6
  exports.platform = ['-p, --platform <platform-name>', '编译平台,默认h5', 'h5'];
@@ -27,3 +27,5 @@ exports.weixinCli = ['--cli.weixin <cli-path>', '微信开发者工具 Cli路径
27
27
  exports.alipayCli = ['--cli.alipay <cli-path>', '支付宝开发者工具 Cli路径'];
28
28
  exports.cosSecretid = ['--cos.secretid <secretid>', '设置腾讯云上传秘钥ID'];
29
29
  exports.cosSecretkey = ['--cos.secretkey <secretkey>', '设置腾讯云上传秘钥KEY'];
30
+ exports.skillRepo = ['--skill.repo <repo-url>', '技能仓库 Git 地址'];
31
+ exports.templateRepo = ['--template.repo <repo-url>', '项目模板仓库 Git 地址'];
@@ -15,3 +15,5 @@ export declare const MAINFEST_PATH: string;
15
15
  export { HOME_PATH };
16
16
  export declare const PLATFORM_OPTIONS: readonly ["h5", "mp-alipay", "mp-baidu", "mp-jd", "mp-kuaishou", "mp-qq", "mp-toutiao", "mp-weixin", "app", "app-ios", "app-android", "app-harmony", "windows", "macos", "linux"];
17
17
  export declare const COMPILER_OPTIONS: readonly ["vite", "uni", "electron-vite"];
18
+ export declare const DEFAULT_SKILL_REPO = "http://10.10.10.16/caoben/project-template.git";
19
+ export declare const DEFAULT_TEMPLATE_REPO = "http://10.10.10.16/caoben/project-template.git";