bfi-cli 0.1.78 → 0.1.80

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/dist/cli.mjs CHANGED
@@ -8199,7 +8199,6 @@ function timeOf(args, required = true) {
8199
8199
  console.error(err);
8200
8200
  process.exit(1);
8201
8201
  }
8202
- if (t && !err) validateTime(t);
8203
8202
  return t ? { time: t } : {};
8204
8203
  }
8205
8204
  function timeOpts(args) {
@@ -9188,6 +9187,43 @@ async function runEvent(args, globalOpts) {
9188
9187
  console.error(`未知子命令: ${sub}。运行 bfi event --help`);
9189
9188
  process.exit(1);
9190
9189
  }
9190
+ async function runDb(args, globalOpts) {
9191
+ const sub = args[0];
9192
+ const rest = args.slice(1);
9193
+ if (!sub || sub === "--help" || sub === "-h") {
9194
+ console.log(`bfi db — DB 取证辅助命令
9195
+
9196
+ 用法:
9197
+ bfi db tenant-locate <租户编码> # 按租户定位分库/实例(ywb 实时查询)
9198
+ 返回 env_code(可直接用于 db_execute/db_explain,如 core1_3)+ dbhost + 数据中心 + 租户中文名
9199
+ 触发场景:① 表名带租户后缀(tb_dimindex_qyic8c7o)② SQL 中 ytenant_id/tenant_id = 值,
9200
+ 且目标分库未知——先定位再连,禁止分库盲枚举
9201
+ 找不到租户返回 found=false(正常情况)
9202
+ 全局: --json / --dry-run / --token <tok>`);
9203
+ return;
9204
+ }
9205
+ if (sub !== "tenant-locate") {
9206
+ console.error(`未知子命令: ${sub}。运行 bfi db --help`);
9207
+ process.exit(1);
9208
+ }
9209
+ const tenantId = positionals(rest)[0];
9210
+ if (!tenantId) {
9211
+ console.error("用法: bfi db tenant-locate <租户编码>(如 t78xbvzp)");
9212
+ process.exit(1);
9213
+ }
9214
+ const jsonMode = flag(rest, "--json");
9215
+ const dryRun = flag(rest, "--dry-run");
9216
+ const api = new YmcApi(globalOpts.token ?? null, void 0, dryRun);
9217
+ if (!dryRun && !api.token) {
9218
+ console.error("未认证。先运行:bfi auth login --token <sk-token>(或传 --token)");
9219
+ process.exit(1);
9220
+ }
9221
+ emit(await api.call("db/tenant-locate", { tenant_id: tenantId }), jsonMode, (data) => {
9222
+ const d = data;
9223
+ if (!d.found) return `未找到租户 ${tenantId}(ywb 无记录,非表不存在)——${d.note ?? ""}`;
9224
+ return d.matches.map((m) => `✓ ${m.env_code ?? "(无法识别 env_code)"} | ${m.tenant_group_name ?? ""} | ${m.tenant_ds_name}\n dbhost=${m.dbhost} dc=${m.dc} 租户名=${m.tenant_name ?? ""}`).join("\n");
9225
+ });
9226
+ }
9191
9227
  function loadSourceMapConsumer() {
9192
9228
  return createRequire(import.meta.url)("source-map").SourceMapConsumer;
9193
9229
  }
@@ -9603,6 +9639,10 @@ ${BOLD}━━━ 观测查询(ymc)━━━${RESET}
9603
9639
  ymc dump-list / call <route> 诊断文件 / 通用端点透传
9604
9640
  (-e env: test/daily/pre/core1-4/commldev;-t: 10m/2h/3d/4w)
9605
9641
 
9642
+ ${BOLD}━━━ DB 取证辅助(db)━━━${RESET}
9643
+ db tenant-locate <租户> 按租户定位分库/实例(表名带租户后缀或 SQL 有
9644
+ ytenant_id 条件且分库未知时,先定位再连)
9645
+
9606
9646
  ${BOLD}━━━ 配置 ━━━${RESET}
9607
9647
  config get [key] 查看配置
9608
9648
  config set <key> <value> [--global] 设置配置
@@ -9876,6 +9916,9 @@ async function main() {
9876
9916
  case "event":
9877
9917
  await runEvent(restArgs, globalOpts);
9878
9918
  break;
9919
+ case "db":
9920
+ await runDb(restArgs, globalOpts);
9921
+ break;
9879
9922
  case "auth":
9880
9923
  if (restArgs[0] === "logout") await runLogout();
9881
9924
  else if (restArgs[0] === "whoami") await runWhoami(globalOpts);
@@ -209,6 +209,9 @@ async function explainSql(envCode, sql, fetchImpl) {
209
209
  sql: requireParam("sql", sql)
210
210
  }, fetchImpl);
211
211
  }
212
+ async function locateTenant(tenantId, fetchImpl) {
213
+ return post("/bficli/api/v2/db/tenant-locate", { tenant_id: tenantId }, fetchImpl);
214
+ }
212
215
  function textResult(payload, isError = false) {
213
216
  return {
214
217
  content: [{
@@ -252,6 +255,10 @@ function buildServer() {
252
255
  ]).optional().describe("环境类型过滤")
253
256
  }
254
257
  }, wrap((args) => listEnvs(args.keyword, args.env_type)));
258
+ server.registerTool("db_tenant_locate", {
259
+ description: "按租户编码定位其所在分库/实例(ywb 实时查询)。返回 env_code(可直接用于 db_execute/db_explain,如 core1_3 / core1_yonyou)+ tenant_ds_name + dbhost + 数据中心 + 租户中文名。触发场景:① 表名带租户后缀(tb_dimindex_qyic8c7o)② SQL 中 ytenant_id/tenant_id = 值,且目标分库未知——先定位再连,禁止分库盲枚举。找不到租户返回 found=false(正常,回退按 SQL 线索定位)。",
260
+ inputSchema: { tenant_id: z.string().min(1, "tenant_id 不能为空:从表名后缀或 SQL 的 ytenant_id/tenant_id 值提取").describe("租户编码(如 t78xbvzp / qyic8c7o)") }
261
+ }, wrap((args) => locateTenant(args.tenant_id)));
255
262
  server.registerTool("db_execute", {
256
263
  description: "在指定环境执行单条 SQL(只读取证)。仅 SELECT/WITH/SHOW/DESC/EXPLAIN;DML/DDL 需环境显式授权位否则 permission_denied。行数上限默认 200。非 mysql 库自动翻译(mysql 语法输入即可)。诊断场景优先 db_explain。",
257
264
  inputSchema: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bfi-cli",
3
- "version": "0.1.78",
3
+ "version": "0.1.80",
4
4
  "description": "用友大业财BFI统一命令行工具,支持技能,技能包,元数据,UI元数据等",
5
5
  "type": "module",
6
6
  "bin": {