zero-ai 1.0.85 → 1.0.86
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/.r2mo/.obsidian/plugins/terminal/manifest.json +14 -0
- package/.r2mo/.obsidian/plugins/terminal/styles.css +32 -0
- package/.r2mo/task/2026-03-07/2026-03-07.12-26-02-TASK@/345/274/200/345/217/221/346/226/260/345/221/275/344/273/244 ai ex-menu.md" +310 -0
- package/.r2mo/task/task-001.md +28 -294
- package/package.json +1 -1
- package/src/commander/auth.json +6 -0
- package/src/commander-ai/fn.ex.auth.js +136 -0
- package/src/commander-ai/index.js +2 -6
- package/.r2mo/.obsidian/themes/Comfort/manifest.json +0 -11
- package/.r2mo/.obsidian/themes/Comfort/theme.css +0 -218
- package/.r2mo/.obsidian/themes/Serenity/manifest.json +0 -7
- package/.r2mo/.obsidian/themes/Serenity/theme.css +0 -7258
- package/.r2mo/.obsidian/themes/W95/manifest.json +0 -8
- package/.r2mo/.obsidian/themes/W95/theme.css +0 -768
- package/src/commander/ex-api.json +0 -8
- package/src/commander/ex-crud.json +0 -1
- package/src/commander/ex-perm.json +0 -8
- package/src/commander-ai/fn.ex.api.js +0 -995
- package/src/commander-ai/fn.ex.crud.js +0 -545
- package/src/commander-ai/fn.ex.perm.js +0 -207
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
const Ec = require("../epic");
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const Ut = require("../commander-shared");
|
|
5
|
-
|
|
6
|
-
const REF_ROLE_ID = "e501b47a-c08b-4c83-b12b-95ad82873e96";
|
|
7
|
-
const REQUIRED_ENV_KEYS = [
|
|
8
|
-
"Z_DB_TYPE", // 数据库类型: MYSQL / SQLSERVER / ORACLE / POSTGRESQL
|
|
9
|
-
"Z_DB_HOST", // 数据库主机
|
|
10
|
-
"Z_DB_PORT", // 数据库端口
|
|
11
|
-
"Z_DBS_INSTANCE", // 业务数据库实例名
|
|
12
|
-
"Z_DB_APP_USER", // 数据库用户
|
|
13
|
-
"Z_DB_APP_PASS" // 数据库密码
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 从 pom.xml 读取当前项目的 artifactId(排除 <parent> 内的)
|
|
18
|
-
*/
|
|
19
|
-
function getArtifactIdFromPom(cwd) {
|
|
20
|
-
const pomPath = path.resolve(cwd, "pom.xml");
|
|
21
|
-
if (!fs.existsSync(pomPath)) return null;
|
|
22
|
-
let content = fs.readFileSync(pomPath, "utf-8");
|
|
23
|
-
content = content.replace(/<parent>[\s\S]*?<\/parent>/i, "");
|
|
24
|
-
const m = content.match(/<artifactId>([^<]+)<\/artifactId>/);
|
|
25
|
-
return m ? m[1].trim() : null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 解析 app.env:export KEY="value" 或 export KEY='value',写入 process.env
|
|
30
|
-
*/
|
|
31
|
-
function loadAppEnv(filePath) {
|
|
32
|
-
if (!fs.existsSync(filePath)) return false;
|
|
33
|
-
const content = fs.readFileSync(filePath, "utf-8");
|
|
34
|
-
const lines = content.split(/\r?\n/);
|
|
35
|
-
for (const line of lines) {
|
|
36
|
-
const trimmed = line.trim();
|
|
37
|
-
if (trimmed.startsWith("#") || !trimmed.startsWith("export ")) continue;
|
|
38
|
-
const match = trimmed.match(/^export\s+([A-Za-z0-9_]+)=["']?([^"'\n]*)["']?/);
|
|
39
|
-
if (match) process.env[match[1]] = match[2].trim();
|
|
40
|
-
}
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 解析 .r2mo/app.env 路径:
|
|
46
|
-
* ONE:当前目录 .r2mo/app.env
|
|
47
|
-
* DPA:{id}-api/.r2mo/app.env,id 来自 pom.xml 或当前目录名
|
|
48
|
-
* 支持两种布局:api 在项目内 (cwd/{id}-api) 或 与项目并列 (cwd/../{id}-api)
|
|
49
|
-
*/
|
|
50
|
-
function resolveAppEnvPath(cwd) {
|
|
51
|
-
const primary = path.resolve(cwd, ".r2mo", "app.env");
|
|
52
|
-
if (fs.existsSync(primary)) return primary;
|
|
53
|
-
|
|
54
|
-
let artifactId = getArtifactIdFromPom(cwd);
|
|
55
|
-
if (!artifactId) {
|
|
56
|
-
const base = path.basename(cwd);
|
|
57
|
-
if (base && base !== ".") artifactId = base;
|
|
58
|
-
}
|
|
59
|
-
if (artifactId) {
|
|
60
|
-
const apiDir = `${artifactId}-api`;
|
|
61
|
-
const nested = path.resolve(cwd, apiDir, ".r2mo", "app.env");
|
|
62
|
-
if (fs.existsSync(nested)) return nested;
|
|
63
|
-
const sibling = path.resolve(cwd, "..", apiDir, ".r2mo", "app.env");
|
|
64
|
-
if (fs.existsSync(sibling)) return sibling;
|
|
65
|
-
}
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
module.exports = async (options) => {
|
|
70
|
-
try {
|
|
71
|
-
const parsed = Ut.parseArgument(options);
|
|
72
|
-
const roleInput = parsed.role;
|
|
73
|
-
if (!roleInput || !String(roleInput).trim()) {
|
|
74
|
-
Ec.error("缺少必需参数:角色(NAME 或 CODE)");
|
|
75
|
-
Ec.info("参数格式:");
|
|
76
|
-
Ec.info(" -r <角色> 或 --role <角色>");
|
|
77
|
-
Ec.info("示例:");
|
|
78
|
-
Ec.info(" ai ex-perm -r 管理员");
|
|
79
|
-
Ec.info(" ai ex-perm --role ADMIN");
|
|
80
|
-
process.exit(1);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
Ec.execute(`ai ex-perm:目标角色(-r / --role)= ${roleInput}`);
|
|
84
|
-
|
|
85
|
-
const cwd = process.cwd();
|
|
86
|
-
const appEnvPath = resolveAppEnvPath(cwd);
|
|
87
|
-
if (!appEnvPath) {
|
|
88
|
-
const tried = [path.resolve(cwd, ".r2mo", "app.env")];
|
|
89
|
-
const id = getArtifactIdFromPom(cwd) || path.basename(cwd);
|
|
90
|
-
if (id) {
|
|
91
|
-
tried.push(path.resolve(cwd, `${id}-api`, ".r2mo", "app.env"));
|
|
92
|
-
tried.push(path.resolve(cwd, "..", `${id}-api`, ".r2mo", "app.env"));
|
|
93
|
-
}
|
|
94
|
-
Ec.error(".r2mo/app.env 不存在;DPA 下也未找到 {id}-api/.r2mo/app.env");
|
|
95
|
-
Ec.info("已尝试路径(id=" + (id || "未解析") + "):");
|
|
96
|
-
tried.forEach((p) => Ec.info(` - ${p}`));
|
|
97
|
-
Ec.info("请确认:1) 在项目根执行 2) 存在 .r2mo/app.env 或 {id}-api/.r2mo/app.env(嵌套或与项目并列)");
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
loadAppEnv(appEnvPath);
|
|
101
|
-
Ec.info(`已加载环境变量:${appEnvPath}`);
|
|
102
|
-
|
|
103
|
-
// 直接检查环境变量(不依赖文件内容;可来自 .r2mo/app.env 或当前 shell 已 export)
|
|
104
|
-
const missing = REQUIRED_ENV_KEYS.filter((k) => !process.env[k] || !String(process.env[k]).trim());
|
|
105
|
-
if (missing.length > 0) {
|
|
106
|
-
Ec.error("环境变量不齐,以下前置条件必须全部已设置,否则不执行。");
|
|
107
|
-
Ec.info("当前缺失的环境变量:" + missing.join(", "));
|
|
108
|
-
Ec.info("请确保以下环境变量已设置(可在 .r2mo/app.env 中 export,或在当前 shell 中 export):");
|
|
109
|
-
Ec.info(" Z_DB_TYPE # 数据库类型: MYSQL / SQLSERVER / ORACLE / POSTGRESQL");
|
|
110
|
-
Ec.info(" Z_DB_HOST # 数据库主机,如 127.0.0.1");
|
|
111
|
-
Ec.info(" Z_DB_PORT # 数据库端口,如 3306");
|
|
112
|
-
Ec.info(" Z_DBS_INSTANCE # 业务数据库实例名");
|
|
113
|
-
Ec.info(" Z_DB_APP_USER # 数据库用户");
|
|
114
|
-
Ec.info(" Z_DB_APP_PASS # 数据库密码");
|
|
115
|
-
process.exit(1);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const mysql = require("mysql2/promise");
|
|
119
|
-
const dbConfig = {
|
|
120
|
-
host: process.env.Z_DB_HOST || "localhost",
|
|
121
|
-
port: parseInt(process.env.Z_DB_PORT || "3306", 10),
|
|
122
|
-
user: process.env.Z_DB_APP_USER,
|
|
123
|
-
password: process.env.Z_DB_APP_PASS,
|
|
124
|
-
database: process.env.Z_DBS_INSTANCE
|
|
125
|
-
};
|
|
126
|
-
Ec.execute(`连接数据库:${dbConfig.database} @ ${dbConfig.host}:${dbConfig.port}(用户 ${dbConfig.user})`);
|
|
127
|
-
|
|
128
|
-
const conn = await mysql.createConnection(dbConfig);
|
|
129
|
-
try {
|
|
130
|
-
Ec.execute("查询 S_ROLE 表:按 NAME 或 CODE 匹配角色…");
|
|
131
|
-
const [rowsRole] = await conn.execute(
|
|
132
|
-
"SELECT ID, NAME, CODE FROM S_ROLE WHERE NAME = ? OR CODE = ? LIMIT 1",
|
|
133
|
-
[roleInput.trim(), roleInput.trim()]
|
|
134
|
-
);
|
|
135
|
-
if (!rowsRole || rowsRole.length === 0) {
|
|
136
|
-
Ec.error(`查询不到角色:${roleInput}`);
|
|
137
|
-
Ec.info("请确认 S_ROLE 表中存在该 NAME 或 CODE;可在库中执行:SELECT ID, NAME, CODE FROM S_ROLE; 查看已有角色。");
|
|
138
|
-
process.exit(1);
|
|
139
|
-
}
|
|
140
|
-
const targetRoleId = rowsRole[0].ID;
|
|
141
|
-
Ec.info(`已找到角色:ID=${targetRoleId},NAME=${rowsRole[0].NAME || "-"},CODE=${rowsRole[0].CODE || "-"}`);
|
|
142
|
-
|
|
143
|
-
Ec.execute(`查询参考角色权限:R_ROLE_PERM,ROLE_ID = ${REF_ROLE_ID}`);
|
|
144
|
-
const [refPerms] = await conn.execute(
|
|
145
|
-
"SELECT * FROM R_ROLE_PERM WHERE ROLE_ID = ?",
|
|
146
|
-
[REF_ROLE_ID]
|
|
147
|
-
);
|
|
148
|
-
if (!refPerms || refPerms.length === 0) {
|
|
149
|
-
Ec.info(`参考角色 ${REF_ROLE_ID} 在 R_ROLE_PERM 中无记录,无需复制。`);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
Ec.info(`参考角色共 ${refPerms.length} 条权限,开始复制到角色 ${targetRoleId}…`);
|
|
153
|
-
|
|
154
|
-
const columns = Object.keys(refPerms[0]);
|
|
155
|
-
const placeholders = columns.map(() => "?").join(", ");
|
|
156
|
-
const colList = columns.map((c) => "`" + c + "`").join(", ");
|
|
157
|
-
let inserted = 0;
|
|
158
|
-
let skipped = 0;
|
|
159
|
-
|
|
160
|
-
for (const row of refPerms) {
|
|
161
|
-
const values = columns.map((col) => (col === "ROLE_ID" ? targetRoleId : row[col]));
|
|
162
|
-
try {
|
|
163
|
-
const [result] = await conn.execute(
|
|
164
|
-
`INSERT IGNORE INTO R_ROLE_PERM (${colList}) VALUES (${placeholders})`,
|
|
165
|
-
values
|
|
166
|
-
);
|
|
167
|
-
if (result && result.affectedRows > 0) inserted++;
|
|
168
|
-
else skipped++;
|
|
169
|
-
} catch (err) {
|
|
170
|
-
if (err.code === "ER_DUP_ENTRY" || err.errno === 1062) skipped++;
|
|
171
|
-
else throw err;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Report:详细汇总
|
|
176
|
-
const sep = "----------------------------------------";
|
|
177
|
-
Ec.info(sep);
|
|
178
|
-
Ec.info(" ai perm 执行报告");
|
|
179
|
-
Ec.info(sep);
|
|
180
|
-
Ec.info(" ⚙️ 环境");
|
|
181
|
-
Ec.info(` app.env : ${appEnvPath}`);
|
|
182
|
-
Ec.info(` 数据库类型 : ${process.env.Z_DB_TYPE || "-"}`);
|
|
183
|
-
Ec.info(` 数据库实例 : ${dbConfig.database}`);
|
|
184
|
-
Ec.info(` 连接地址 : ${dbConfig.host}:${dbConfig.port}`);
|
|
185
|
-
Ec.info(` 数据库用户 : ${dbConfig.user}`);
|
|
186
|
-
Ec.info(" 👤 目标角色(-r 指定)");
|
|
187
|
-
Ec.info(` 输入 : ${roleInput}`);
|
|
188
|
-
Ec.info(` ID : ${targetRoleId}`);
|
|
189
|
-
Ec.info(` NAME : ${rowsRole[0].NAME ?? "-"}`);
|
|
190
|
-
Ec.info(` CODE : ${rowsRole[0].CODE ?? "-"}`);
|
|
191
|
-
Ec.info(" 📋 参考角色(复制来源)");
|
|
192
|
-
Ec.info(` ROLE_ID : ${REF_ROLE_ID}`);
|
|
193
|
-
Ec.info(` R_ROLE_PERM 条数 : ${refPerms.length}`);
|
|
194
|
-
Ec.info(" ✅ 权限复制结果");
|
|
195
|
-
Ec.info(` 本次插入 : ${inserted} 条`);
|
|
196
|
-
Ec.info(` 重复跳过 : ${skipped} 条`);
|
|
197
|
-
Ec.info(` 合计处理 : ${inserted + skipped} 条`);
|
|
198
|
-
Ec.info(sep);
|
|
199
|
-
} finally {
|
|
200
|
-
await conn.end();
|
|
201
|
-
}
|
|
202
|
-
} catch (err) {
|
|
203
|
-
Ec.error(`执行失败:${err.message}`);
|
|
204
|
-
if (err.code) Ec.info(`错误码:${err.code}`);
|
|
205
|
-
process.exit(1);
|
|
206
|
-
}
|
|
207
|
-
};
|