zero-ai 1.0.69 → 1.0.71
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
CHANGED
package/src/commander/sync.json
CHANGED
|
@@ -3,17 +3,8 @@
|
|
|
3
3
|
"description": "同步 Zero Ui 的最新框架",
|
|
4
4
|
"command": "sync",
|
|
5
5
|
"options": [
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"description": "本地配置文件路径,默认 .zero",
|
|
10
|
-
"default": ".zero"
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"name": "mode",
|
|
14
|
-
"alias": "m",
|
|
15
|
-
"description": "指定同步模块的模式,是否本地同步",
|
|
16
|
-
"default": false
|
|
17
|
-
}
|
|
6
|
+
{"name": "path", "alias": "p", "description": "本地配置文件路径,默认 .zero", "default": ".zero"},
|
|
7
|
+
{"name": "mode", "alias": "m", "description": "指定同步模块的模式,是否本地同步", "default": false},
|
|
8
|
+
{"name": "reverse", "alias": "r", "type": "boolean", "description": "逆向拷贝:从当前项目拷贝到 Z_ZERO_UI 指定目录", "default": false}
|
|
18
9
|
]
|
|
19
|
-
}
|
|
10
|
+
}
|
|
@@ -181,6 +181,51 @@ module.exports = async (options) => {
|
|
|
181
181
|
Ec.info(`安装位置:${targetLabels.join("、")}`);
|
|
182
182
|
Ec.info(`已安装 ${selectedFiles.length} 个规则文件`);
|
|
183
183
|
|
|
184
|
+
// work-claude/:提取标题形成菜单,用户选择后拷贝 CLAUDE-*.md 为项目根目录 CLAUDE.md
|
|
185
|
+
const workClaudeDir = path.join(repoCache, "work-claude");
|
|
186
|
+
if (fs.existsSync(workClaudeDir)) {
|
|
187
|
+
const workClaudeFiles = fs.readdirSync(workClaudeDir).filter((file) => {
|
|
188
|
+
const p = path.join(workClaudeDir, file);
|
|
189
|
+
return fs.statSync(p).isFile() && file.startsWith("CLAUDE-") && file.endsWith(".md");
|
|
190
|
+
});
|
|
191
|
+
if (workClaudeFiles.length > 0) {
|
|
192
|
+
const choicesWithTitle = workClaudeFiles.map((file) => {
|
|
193
|
+
const fullPath = path.join(workClaudeDir, file);
|
|
194
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
195
|
+
const match = content.match(/^#\s+(.+)$/m);
|
|
196
|
+
const title = match ? match[1].trim() : path.basename(file, ".md");
|
|
197
|
+
return { name: title, value: file };
|
|
198
|
+
});
|
|
199
|
+
const { selectedClaude } = await inquirer.prompt([
|
|
200
|
+
{
|
|
201
|
+
type: "list",
|
|
202
|
+
name: "selectedClaude",
|
|
203
|
+
message: "请选择要安装的 Claude 工作说明(将拷贝为项目根目录 CLAUDE.md):",
|
|
204
|
+
choices: choicesWithTitle
|
|
205
|
+
}
|
|
206
|
+
]);
|
|
207
|
+
const sourceClaude = path.join(workClaudeDir, selectedClaude);
|
|
208
|
+
const targetClaude = path.resolve(outputPath, "CLAUDE.md");
|
|
209
|
+
fs.copyFileSync(sourceClaude, targetClaude);
|
|
210
|
+
Ec.info(`已安装:${selectedClaude} → CLAUDE.md`);
|
|
211
|
+
// 将 CLAUDE.md 追加到 .gitignore
|
|
212
|
+
const gitignorePathClaude = path.resolve(outputPath, ".gitignore");
|
|
213
|
+
const claudeIgnoreEntry = "CLAUDE.md";
|
|
214
|
+
if (fs.existsSync(gitignorePathClaude)) {
|
|
215
|
+
const content = fs.readFileSync(gitignorePathClaude, "utf-8");
|
|
216
|
+
const hasClaude = content.split("\n").some((line) => line.trim() === claudeIgnoreEntry);
|
|
217
|
+
if (!hasClaude) {
|
|
218
|
+
const newContent = content.endsWith("\n") ? `${content}${claudeIgnoreEntry}\n` : `${content}\n${claudeIgnoreEntry}\n`;
|
|
219
|
+
fs.writeFileSync(gitignorePathClaude, newContent, "utf-8");
|
|
220
|
+
Ec.info(`已将 ${claudeIgnoreEntry} 添加到 .gitignore`);
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
fs.writeFileSync(gitignorePathClaude, `${claudeIgnoreEntry}\n`, "utf-8");
|
|
224
|
+
Ec.info(`已创建 .gitignore 并添加 ${claudeIgnoreEntry}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
184
229
|
// 添加 AI 工具目录到 .git/info/exclude
|
|
185
230
|
const excludeEntries = [".cursor/", ".claude/", ".gemini/", ".trae/", ".lingma/"];
|
|
186
231
|
const gitPath = path.resolve(outputPath, ".git");
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
const Ec = require("../epic");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
2
4
|
const child = require('child_process');
|
|
3
5
|
const Ut = require("../commander-shared");
|
|
4
6
|
|
|
7
|
+
const REPO_URL = "https://gitee.com/silentbalanceyh/scaffold-ui.git";
|
|
8
|
+
const REPO_NAME = "scaffold-ui";
|
|
9
|
+
|
|
5
10
|
const COMMANDS = [
|
|
6
11
|
"run-default.sh",
|
|
7
12
|
"run-doc.sh",
|
|
@@ -60,24 +65,21 @@ const COMMANDS = [
|
|
|
60
65
|
]
|
|
61
66
|
|
|
62
67
|
const executeRemote = (actual = {}, options = {}) => {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
const outputBase = "."; // 仓库与 .gitignore 使用项目根目录
|
|
69
|
+
const repoCache = path.resolve(outputBase, ".r2mo", "repo", REPO_NAME);
|
|
70
|
+
const repoCacheDir = path.dirname(repoCache);
|
|
71
|
+
// 确保 .r2mo/repo 目录存在
|
|
72
|
+
if (!fs.existsSync(repoCacheDir)) {
|
|
73
|
+
fs.mkdirSync(repoCacheDir, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
// 若已有克隆则先删除,再拉取
|
|
76
|
+
if (Ec.isExist(repoCache)) {
|
|
77
|
+
Ec.info(`发现存在旧仓库,正在删除:${repoCache}`);
|
|
78
|
+
child.execSync(`rm -rf ${repoCache}`, options);
|
|
73
79
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
child.execSync(cmdGit, options);
|
|
78
|
-
const cmdRm = `rm -rf ${pathSource}/.git`;
|
|
79
|
-
child.execSync(cmdRm, options);
|
|
80
|
-
return pathSource;
|
|
80
|
+
Ec.info(`拉取最新代码到:${repoCache}`);
|
|
81
|
+
child.execSync(`git clone ${REPO_URL} ${repoCache}`, options);
|
|
82
|
+
return repoCache;
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
const executeLocal = (actual = {}, options = {}) => {
|
|
@@ -89,6 +91,35 @@ const executeLocal = (actual = {}, options = {}) => {
|
|
|
89
91
|
return pathEnv;
|
|
90
92
|
}
|
|
91
93
|
|
|
94
|
+
/**
|
|
95
|
+
* 逆向拷贝:从当前项目将 COMMANDS 所列内容拷贝到 Z_ZERO_UI 指定目录
|
|
96
|
+
*/
|
|
97
|
+
const executeReverse = (targetBase, options = {}) => {
|
|
98
|
+
Ec.info(`逆向拷贝目标:${targetBase}`);
|
|
99
|
+
Ec.info(`开始逆向拷贝主框架(与正向 sync 相同内容):......`.yellow);
|
|
100
|
+
COMMANDS.forEach((command) => {
|
|
101
|
+
Ec.info(`处理:${command.green}`);
|
|
102
|
+
const src = `./${command}`;
|
|
103
|
+
const dest = path.resolve(targetBase, command);
|
|
104
|
+
if (command.endsWith("/")) {
|
|
105
|
+
if (!Ec.isExist(src)) return;
|
|
106
|
+
const destDir = path.resolve(targetBase, command);
|
|
107
|
+
if (!fs.existsSync(destDir)) {
|
|
108
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
child.execSync(`cp -rf ${src}* "${destDir}"`, options);
|
|
111
|
+
} else {
|
|
112
|
+
if (!Ec.isExist(src)) return;
|
|
113
|
+
const destDir = path.dirname(dest);
|
|
114
|
+
if (!fs.existsSync(destDir)) {
|
|
115
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
116
|
+
}
|
|
117
|
+
child.execSync(`cp -rf ${src} "${dest}"`, options);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
Ec.info(`逆向拷贝完成:${targetBase}!`.help);
|
|
121
|
+
};
|
|
122
|
+
|
|
92
123
|
module.exports = (options) => {
|
|
93
124
|
|
|
94
125
|
// 获取当前操作系统
|
|
@@ -105,6 +136,14 @@ module.exports = (options) => {
|
|
|
105
136
|
optionsWait = {stdio: 'inherit'};
|
|
106
137
|
}
|
|
107
138
|
|
|
139
|
+
// -r / --reverse 无值时补 "true",否则 parseArgument 会报缺值
|
|
140
|
+
const argvRest = process.argv.slice(3);
|
|
141
|
+
const rIdx = argvRest.indexOf("-r");
|
|
142
|
+
const revIdx = argvRest.indexOf("--reverse");
|
|
143
|
+
const flagIdx = rIdx >= 0 ? rIdx : revIdx;
|
|
144
|
+
if (flagIdx >= 0 && (flagIdx + 1 >= argvRest.length || (argvRest[flagIdx + 1] && argvRest[flagIdx + 1].startsWith("-")))) {
|
|
145
|
+
process.argv.splice(3 + flagIdx + 1, 0, "true");
|
|
146
|
+
}
|
|
108
147
|
const parsed = Ut.parseArgument(options);
|
|
109
148
|
// 1. 环境检查
|
|
110
149
|
if (!Ec.isExist(".git")) {
|
|
@@ -112,6 +151,18 @@ module.exports = (options) => {
|
|
|
112
151
|
return;
|
|
113
152
|
}
|
|
114
153
|
|
|
154
|
+
// 逆向拷贝:-r 时从当前项目拷贝到 Z_ZERO_UI
|
|
155
|
+
if (parsed.reverse) {
|
|
156
|
+
const targetBase = process.env.Z_ZERO_UI;
|
|
157
|
+
if (!targetBase || !targetBase.trim()) {
|
|
158
|
+
Ec.error("逆向拷贝需要设置环境变量 Z_ZERO_UI(拷贝目标地址),未设置则退出。");
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
const resolved = path.resolve(targetBase.trim());
|
|
162
|
+
executeReverse(resolved, optionsWait);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
115
166
|
let pathSource;
|
|
116
167
|
if (parsed.mode) {
|
|
117
168
|
// 本地模式
|
|
@@ -121,26 +172,45 @@ module.exports = (options) => {
|
|
|
121
172
|
pathSource = executeRemote(parsed, optionsWait);
|
|
122
173
|
}
|
|
123
174
|
if (pathSource) {
|
|
124
|
-
|
|
175
|
+
const outputBase = ".";
|
|
176
|
+
// 确保 .r2mo/repo 在 .gitignore 中
|
|
177
|
+
const gitignorePath = path.resolve(outputBase, ".gitignore");
|
|
178
|
+
const ignoreEntry = ".r2mo/repo/";
|
|
179
|
+
if (fs.existsSync(gitignorePath)) {
|
|
180
|
+
const gitignoreContent = fs.readFileSync(gitignorePath, "utf-8");
|
|
181
|
+
const hasIgnoreEntry = gitignoreContent.split("\n").some((line) => {
|
|
182
|
+
const t = line.trim();
|
|
183
|
+
return t === ".r2mo/repo" || t === ".r2mo/repo/";
|
|
184
|
+
});
|
|
185
|
+
if (!hasIgnoreEntry) {
|
|
186
|
+
const newContent = gitignoreContent.endsWith("\n")
|
|
187
|
+
? `${gitignoreContent}${ignoreEntry}\n`
|
|
188
|
+
: `${gitignoreContent}\n${ignoreEntry}\n`;
|
|
189
|
+
fs.writeFileSync(gitignorePath, newContent, "utf-8");
|
|
190
|
+
Ec.info(`已将 ${ignoreEntry} 添加到 .gitignore`);
|
|
191
|
+
}
|
|
192
|
+
} else {
|
|
193
|
+
fs.writeFileSync(gitignorePath, `${ignoreEntry}\n`, "utf-8");
|
|
194
|
+
Ec.info(`已创建 .gitignore 并添加 ${ignoreEntry}`);
|
|
195
|
+
}
|
|
196
|
+
// 拷贝框架文件
|
|
125
197
|
Ec.info(`开始更新主框架:......`.yellow);
|
|
126
198
|
COMMANDS.forEach(command => {
|
|
127
199
|
Ec.info(`处理目录:${command.green}`);
|
|
128
|
-
let cmd;
|
|
129
200
|
if (command.endsWith("/")) {
|
|
130
|
-
// 目录拷贝
|
|
131
201
|
if (!Ec.isExist(command)) {
|
|
132
|
-
|
|
133
|
-
child.execSync(cmdDir, optionsWait);
|
|
202
|
+
child.execSync(`mkdir -p ${command}`, optionsWait);
|
|
134
203
|
}
|
|
135
|
-
|
|
136
|
-
child.execSync(cmd, optionsWait);
|
|
204
|
+
child.execSync(`cp -rf ${pathSource}/${command}* ./${command}`, optionsWait);
|
|
137
205
|
} else {
|
|
138
|
-
|
|
139
|
-
cmd = `cp -rf ${pathSource}/${command} ./${command}`;
|
|
140
|
-
child.execSync(cmd, optionsWait);
|
|
206
|
+
child.execSync(`cp -rf ${pathSource}/${command} ./${command}`, optionsWait);
|
|
141
207
|
}
|
|
142
|
-
})
|
|
208
|
+
});
|
|
143
209
|
Ec.info(`主框架更新完成:${pathSource}!`.help);
|
|
210
|
+
// 拷贝完成后移除临时仓库
|
|
211
|
+
Ec.info(`正在移除临时仓库:${pathSource}`);
|
|
212
|
+
child.execSync(`rm -rf ${pathSource}`, optionsWait);
|
|
213
|
+
Ec.info(`临时仓库已移除。`);
|
|
144
214
|
}
|
|
145
215
|
}
|
|
146
216
|
/**
|