bfi-cli 0.1.108 → 0.1.109

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.
Files changed (2) hide show
  1. package/dist/cli.mjs +55 -28
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -8714,6 +8714,31 @@ async function runInstall(args, globalOpts) {
8714
8714
  console.log();
8715
8715
  }
8716
8716
  const YMC_DEFAULT_BASE = process.env.BFI_YMC_BASE || "https://bfi.yyuap.com/bfi-api/bficli/api/v2";
8717
+ function messageOf(parsed) {
8718
+ const raw = parsed.msg ?? parsed.message;
8719
+ if (typeof raw === "string") return raw;
8720
+ if (raw === void 0 || raw === null) return "";
8721
+ try {
8722
+ return JSON.stringify(raw);
8723
+ } catch {
8724
+ return String(raw);
8725
+ }
8726
+ }
8727
+ function describeApiError(parsed, status, raw = "") {
8728
+ const prefix = status >= 400 ? `HTTP ${status} ` : "";
8729
+ const detail = parsed.detail;
8730
+ if (Array.isArray(detail) && detail.length > 0) return `${prefix}${detail.map((item) => {
8731
+ if (!item || typeof item !== "object") return String(item);
8732
+ const o = item;
8733
+ const loc = Array.isArray(o.loc) ? o.loc.map(String).join(".") : "";
8734
+ const msg = o.msg ?? o.message ?? o.type ?? "参数错误";
8735
+ return loc ? `${loc}: ${String(msg)}` : String(msg);
8736
+ }).join("; ")}`;
8737
+ if (detail !== void 0 && detail !== null) return `${prefix}${typeof detail === "string" ? detail : JSON.stringify(detail)}`;
8738
+ const msg = messageOf(parsed);
8739
+ if (msg.trim()) return `${prefix}${msg}`;
8740
+ return `${prefix}${raw.trim().slice(0, 200) || "服务端未返回错误信息"}`;
8741
+ }
8717
8742
  var YmcApi = class {
8718
8743
  baseUrl;
8719
8744
  token;
@@ -8732,12 +8757,12 @@ var YmcApi = class {
8732
8757
  if (body !== void 0 && Object.keys(body).length > 0) console.log(JSON.stringify(body, null, 2));
8733
8758
  process.exit(0);
8734
8759
  }
8735
- async call(path, body = {}, timeoutMs = 9e4) {
8760
+ async call(path, body = {}, timeoutMs = 12e4) {
8736
8761
  if (this.dryRun) this._dryRunExit("POST", path, body);
8737
8762
  const url = `${this.baseUrl}/${path.replace(/^\//, "")}`;
8738
8763
  const payload = JSON.stringify(body);
8739
8764
  const mod = url.startsWith("https://") ? https : http;
8740
- const raw = await new Promise((resolve, reject) => {
8765
+ const { status, text: raw } = await new Promise((resolve, reject) => {
8741
8766
  const req = mod.request(url, {
8742
8767
  method: "POST",
8743
8768
  headers: {
@@ -8750,7 +8775,10 @@ var YmcApi = class {
8750
8775
  }, (res) => {
8751
8776
  const chunks = [];
8752
8777
  res.on("data", (c) => chunks.push(c));
8753
- res.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
8778
+ res.on("end", () => resolve({
8779
+ status: res.statusCode ?? 0,
8780
+ text: Buffer.concat(chunks).toString("utf-8")
8781
+ }));
8754
8782
  });
8755
8783
  req.on("timeout", () => {
8756
8784
  req.destroy(/* @__PURE__ */ new Error(`请求超时(${timeoutMs}ms)`));
@@ -8763,12 +8791,13 @@ var YmcApi = class {
8763
8791
  try {
8764
8792
  parsed = JSON.parse(raw);
8765
8793
  } catch {
8766
- throw new Error(`非 JSON 响应(HTTP):${raw.slice(0, 200)}`);
8794
+ throw new Error(`HTTP ${status} 非 JSON 响应:${raw.slice(0, 200)}`);
8767
8795
  }
8768
- if (parsed.detail && parsed.code === void 0) throw new Error(String(parsed.detail));
8796
+ if (parsed.detail !== void 0 && parsed.code === void 0) throw new Error(describeApiError(parsed, status, raw));
8797
+ if (status >= 400 && parsed.code === void 0 && parsed.msg === void 0) throw new Error(describeApiError(parsed, status, raw));
8769
8798
  return {
8770
8799
  code: typeof parsed.code === "number" ? parsed.code : -1,
8771
- msg: String(parsed.msg ?? ""),
8800
+ msg: messageOf(parsed),
8772
8801
  data: parsed.data ?? null,
8773
8802
  raw: parsed
8774
8803
  };
@@ -8816,7 +8845,7 @@ var YmcApi = class {
8816
8845
  if (this.dryRun) this._dryRunExit("GET", path);
8817
8846
  const url = `${this.baseUrl}/${path.replace(/^\//, "")}`;
8818
8847
  const mod = url.startsWith("https://") ? https : http;
8819
- const raw = await new Promise((resolve, reject) => {
8848
+ const { status, text: raw } = await new Promise((resolve, reject) => {
8820
8849
  const req = mod.request(url, {
8821
8850
  method: "GET",
8822
8851
  headers: {
@@ -8827,7 +8856,10 @@ var YmcApi = class {
8827
8856
  }, (res) => {
8828
8857
  const chunks = [];
8829
8858
  res.on("data", (c) => chunks.push(c));
8830
- res.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
8859
+ res.on("end", () => resolve({
8860
+ status: res.statusCode ?? 0,
8861
+ text: Buffer.concat(chunks).toString("utf-8")
8862
+ }));
8831
8863
  });
8832
8864
  req.on("timeout", () => {
8833
8865
  req.destroy(/* @__PURE__ */ new Error(`请求超时(${timeoutMs}ms)`));
@@ -8835,11 +8867,16 @@ var YmcApi = class {
8835
8867
  req.on("error", reject);
8836
8868
  req.end();
8837
8869
  });
8838
- const parsed = JSON.parse(raw);
8839
- if (parsed.detail && parsed.code === void 0) throw new Error(String(parsed.detail));
8870
+ let parsed;
8871
+ try {
8872
+ parsed = JSON.parse(raw);
8873
+ } catch {
8874
+ throw new Error(`HTTP ${status} 非 JSON 响应:${raw.slice(0, 200)}`);
8875
+ }
8876
+ if (parsed.detail !== void 0 && parsed.code === void 0) throw new Error(describeApiError(parsed, status, raw));
8840
8877
  return {
8841
8878
  code: typeof parsed.code === "number" ? parsed.code : -1,
8842
- msg: String(parsed.msg ?? ""),
8879
+ msg: messageOf(parsed),
8843
8880
  data: parsed.data ?? null,
8844
8881
  raw: parsed
8845
8882
  };
@@ -8921,7 +8958,6 @@ const F_ENV = [
8921
8958
  "--env",
8922
8959
  "--env-name"
8923
8960
  ];
8924
- const F_TIME = ["-t", "--time"];
8925
8961
  const F_RANGE = [
8926
8962
  "-t",
8927
8963
  "--time",
@@ -8941,7 +8977,7 @@ const ALLOWED_FLAGS = {
8941
8977
  ],
8942
8978
  "sls-grep": [
8943
8979
  ...F_ENV,
8944
- ...F_TIME,
8980
+ ...F_RANGE,
8945
8981
  "--group-by",
8946
8982
  "--line",
8947
8983
  "--app"
@@ -9091,15 +9127,6 @@ function requireEnv(args) {
9091
9127
  }
9092
9128
  return { env_name: env };
9093
9129
  }
9094
- function timeOf(args, required = true) {
9095
- const t = opt(args, "-t", "--time");
9096
- const err = timeError(t);
9097
- if (err && required) {
9098
- console.error(err);
9099
- process.exit(1);
9100
- }
9101
- return t ? { time: t } : {};
9102
- }
9103
9130
  function timeOpts(args) {
9104
9131
  const out = {};
9105
9132
  const t = opt(args, "-t", "--time");
@@ -9192,7 +9219,7 @@ async function runYmc(args, globalOpts) {
9192
9219
  trace_id: id,
9193
9220
  ...requireEnv(rest),
9194
9221
  ...opt(rest, "--ts") ? { ts: Number(opt(rest, "--ts")) } : {}
9195
- }), jsonMode, (data) => {
9222
+ }, 18e4), jsonMode, (data) => {
9196
9223
  const d = data;
9197
9224
  const lines = [];
9198
9225
  const wc = d.warning_chain;
@@ -9277,7 +9304,7 @@ async function runYmc(args, globalOpts) {
9277
9304
  case "sls-grep": {
9278
9305
  const kw = positionals(rest)[0];
9279
9306
  if (!kw) {
9280
- console.error("用法:bfi ymc sls-grep \"<关键词>\" -e <env> [-t time] [--app <appCode>] [--group-by applicationName|message|requestURL]");
9307
+ console.error("用法:bfi ymc sls-grep \"<关键词>\" -e <env> [-t <time> | --start-time <s> --end-time <e>] [--app <appCode>] [--group-by applicationName|message|requestURL]");
9281
9308
  console.error("例:bfi ymc sls-grep \"ClassCastException\" -e daily -t 3d");
9282
9309
  console.error("⚠️ 关键词按「整值」匹配:类名/全限定异常名必须整串加引号");
9283
9310
  console.error(" (\"java.lang.OutOfMemoryError\" 命中;简写 \"OutOfMemoryError\" 恒 0 且不报错)——sls-discipline §3");
@@ -9292,7 +9319,7 @@ async function runYmc(args, globalOpts) {
9292
9319
  emit(await api.call("sls/raw", {
9293
9320
  query,
9294
9321
  ...requireEnv(rest),
9295
- ...timeOf(rest, false),
9322
+ ...timeOpts(rest),
9296
9323
  line: Number(opt(rest, "--line") || 50)
9297
9324
  }), jsonMode, aggSummary(`SLS 全文检索 "${kw}"`));
9298
9325
  break;
@@ -9404,7 +9431,7 @@ async function runYmc(args, globalOpts) {
9404
9431
  };
9405
9432
  const app = opt(rest, "--app");
9406
9433
  if (app) body.filters = { service_name: app };
9407
- emit(await api.call("kibana/stats", body), jsonMode, (data) => {
9434
+ emit(await api.call("kibana/stats", body, 18e4), jsonMode, (data) => {
9408
9435
  const d = data;
9409
9436
  const a = d.aggs;
9410
9437
  return `✓ URL 统计${app ? ` [${app}]` : "(⚠️ 未限定服务,共享路径为全平台混合)"}: QPS=${a.qps} avg=${a.avg_rt?.value ?? "-"} 慢请求Top=${Array.isArray(d.slow_top) ? d.slow_top.length : 0}`;
@@ -9429,7 +9456,7 @@ async function runYmc(args, globalOpts) {
9429
9456
  console.error("用法:bfi ymc ingress --trace-id <id> | --uri </path> [-app <service_name>] -e <env> [-t time]");
9430
9457
  process.exit(1);
9431
9458
  }
9432
- emit(await api.call("kibana/search", body), jsonMode, rowsSummary("ingress 日志"));
9459
+ emit(await api.call("kibana/search", body, 18e4), jsonMode, rowsSummary("ingress 日志"));
9433
9460
  break;
9434
9461
  }
9435
9462
  case "dump-list": {
@@ -9721,7 +9748,7 @@ const HELP = {
9721
9748
  bfi ymc sls-raw 'applicationname: yonbip-scm-scmmp AND "unaudit" | SELECT traceid, time LIMIT 10' -e core3 -t 1d
9722
9749
  注意:业务关键词检索必须 applicationname: 限定目标服务(共享路径 URL 全平台都有);
9723
9750
  traceid/spanid 检索例外(全局唯一)。非索引字段(logger/requesturl)不能进检索语法,只能在 SELECT 里引用。`,
9724
- "sls-grep": `bfi ymc sls-grep "<关键词>" -e <env> -t <time> [--app <appCode>] [--group-by <字段>] [--json]
9751
+ "sls-grep": `bfi ymc sls-grep "<关键词>" -e <env> [-t <time> | --start-time <s> --end-time <e>] [--app <appCode>] [--group-by <字段>] [--json]
9725
9752
  SLS 全文检索聚合(每组计数精确不封顶;组数上限 500——实测 2026-09-17:计数不受限,仅组数受 SLS 默认 LIMIT 约束,服务端已放宽)。
9726
9753
  ⚠️ 关键词按「整值」匹配:类名/全限定异常名必须整串加引号
9727
9754
  ("java.lang.OutOfMemoryError" 命中;简写 "OutOfMemoryError" 恒 0 命中且不报错)——sls-discipline §3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bfi-cli",
3
- "version": "0.1.108",
3
+ "version": "0.1.109",
4
4
  "description": "用友大业财BFI统一命令行工具,支持技能,技能包,元数据,UI元数据等",
5
5
  "type": "module",
6
6
  "bin": {