bfi-cli 0.1.68 → 0.1.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/dist/cli.mjs +165 -9
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -7996,15 +7996,23 @@ const YMC_DEFAULT_BASE = process.env.BFI_YMC_BASE || "http://172.20.35.178:8901/
|
|
|
7996
7996
|
var YmcApi = class {
|
|
7997
7997
|
baseUrl;
|
|
7998
7998
|
token;
|
|
7999
|
-
|
|
7999
|
+
dryRun;
|
|
8000
|
+
constructor(token = null, baseUrl, dryRun = false) {
|
|
8000
8001
|
this.baseUrl = (baseUrl || YMC_DEFAULT_BASE).replace(/\/$/, "");
|
|
8002
|
+
this.dryRun = dryRun;
|
|
8001
8003
|
if (token) {
|
|
8002
8004
|
this.token = token;
|
|
8003
8005
|
return;
|
|
8004
8006
|
}
|
|
8005
8007
|
this.token = loadGlobalConfig()?.token ?? null;
|
|
8006
8008
|
}
|
|
8009
|
+
_dryRunExit(method, path, body) {
|
|
8010
|
+
console.log(`[dry-run] ${method} ${this.baseUrl}/${path.replace(/^\//, "")}`);
|
|
8011
|
+
if (body !== void 0 && Object.keys(body).length > 0) console.log(JSON.stringify(body, null, 2));
|
|
8012
|
+
process.exit(0);
|
|
8013
|
+
}
|
|
8007
8014
|
async call(path, body = {}, timeoutMs = 9e4) {
|
|
8015
|
+
if (this.dryRun) this._dryRunExit("POST", path, body);
|
|
8008
8016
|
const url = `${this.baseUrl}/${path.replace(/^\//, "")}`;
|
|
8009
8017
|
const payload = JSON.stringify(body);
|
|
8010
8018
|
const mod = url.startsWith("https://") ? https : http;
|
|
@@ -8045,6 +8053,11 @@ var YmcApi = class {
|
|
|
8045
8053
|
};
|
|
8046
8054
|
}
|
|
8047
8055
|
async download(path, body, outFile, timeoutMs = 18e4) {
|
|
8056
|
+
if (this.dryRun) {
|
|
8057
|
+
console.log(`[dry-run] POST ${this.baseUrl}/${path.replace(/^\//, "")} (响应写盘 → ${outFile})`);
|
|
8058
|
+
if (Object.keys(body).length > 0) console.log(JSON.stringify(body, null, 2));
|
|
8059
|
+
process.exit(0);
|
|
8060
|
+
}
|
|
8048
8061
|
const url = `${this.baseUrl}/${path.replace(/^\//, "")}`;
|
|
8049
8062
|
const payload = JSON.stringify(body);
|
|
8050
8063
|
const mod = url.startsWith("https://") ? https : http;
|
|
@@ -8078,6 +8091,7 @@ var YmcApi = class {
|
|
|
8078
8091
|
return raw.length;
|
|
8079
8092
|
}
|
|
8080
8093
|
async get(path, timeoutMs = 3e4) {
|
|
8094
|
+
if (this.dryRun) this._dryRunExit("GET", path);
|
|
8081
8095
|
const url = `${this.baseUrl}/${path.replace(/^\//, "")}`;
|
|
8082
8096
|
const mod = url.startsWith("https://") ? https : http;
|
|
8083
8097
|
const raw = await new Promise((resolve, reject) => {
|
|
@@ -8189,13 +8203,22 @@ async function runYmc(args, globalOpts) {
|
|
|
8189
8203
|
const sub = args[0];
|
|
8190
8204
|
const rest = args.slice(1);
|
|
8191
8205
|
const jsonMode = flag(rest, "--json");
|
|
8206
|
+
const dryRun = flag(rest, "--dry-run");
|
|
8192
8207
|
const token = globalOpts.token;
|
|
8193
|
-
const api = new YmcApi(token ?? null);
|
|
8194
|
-
requireToken(api);
|
|
8208
|
+
const api = new YmcApi(token ?? null, void 0, dryRun);
|
|
8195
8209
|
if (!sub || sub === "--help" || sub === "-h") {
|
|
8196
8210
|
printHelp();
|
|
8197
8211
|
return;
|
|
8198
8212
|
}
|
|
8213
|
+
if (sub === "help") {
|
|
8214
|
+
printCommandHelp(rest[0] || "");
|
|
8215
|
+
return;
|
|
8216
|
+
}
|
|
8217
|
+
if (flag(rest, "--help") || flag(rest, "-h")) {
|
|
8218
|
+
printCommandHelp(sub);
|
|
8219
|
+
return;
|
|
8220
|
+
}
|
|
8221
|
+
if (!dryRun) requireToken(api);
|
|
8199
8222
|
switch (sub) {
|
|
8200
8223
|
case "status":
|
|
8201
8224
|
emit(await api.get("ymc/auth/status"), jsonMode, (data) => {
|
|
@@ -8279,6 +8302,7 @@ async function runYmc(args, globalOpts) {
|
|
|
8279
8302
|
...opt(rest, "--days") ? { days: Number(opt(rest, "--days")) } : {},
|
|
8280
8303
|
...opt(rest, "--line") ? { line: Number(opt(rest, "--line")) } : {}
|
|
8281
8304
|
};
|
|
8305
|
+
if (!opt(rest, "-t", "--time") && !opt(rest, "--start-time") && !opt(rest, "--days")) console.error("⚠️ 未指定时间窗:服务端按超大窗口兜底,命中可能含数天前记录——取证请显式 -t/--start-time");
|
|
8282
8306
|
emit(await api.call("sls/raw", body), jsonMode, (data) => {
|
|
8283
8307
|
const d = data;
|
|
8284
8308
|
const rows = Array.isArray(d) ? d : d.rows ?? d.data ?? [];
|
|
@@ -8333,14 +8357,14 @@ async function runYmc(args, globalOpts) {
|
|
|
8333
8357
|
...requireEnv(rest),
|
|
8334
8358
|
...timeOpts(rest),
|
|
8335
8359
|
page: Number(opt(rest, "--page") || 1),
|
|
8336
|
-
pageSize: Number(opt(rest, "--page-size") || 20)
|
|
8360
|
+
pageSize: Number(opt(rest, "--page-size") || 20),
|
|
8361
|
+
enableProfiler: flag(rest, "--no-profiler") ? "false" : "true"
|
|
8337
8362
|
};
|
|
8338
8363
|
for (const [k, name] of [
|
|
8339
8364
|
["sqlStr", "--sql-str"],
|
|
8340
8365
|
["md5Sql", "--md5"],
|
|
8341
8366
|
["traceId", "--trace-id"],
|
|
8342
|
-
["curAppCode", "--app"]
|
|
8343
|
-
["enableProfiler", "--profiler"]
|
|
8367
|
+
["curAppCode", "--app"]
|
|
8344
8368
|
]) {
|
|
8345
8369
|
const v = opt(rest, name);
|
|
8346
8370
|
if (v) body[k] = v;
|
|
@@ -8378,6 +8402,7 @@ async function runYmc(args, globalOpts) {
|
|
|
8378
8402
|
}
|
|
8379
8403
|
const cost = opt(rest, "--min-cost");
|
|
8380
8404
|
if (cost) body.costTime = [Number(cost), 999999];
|
|
8405
|
+
if (flag(rest, "--profiler")) console.error("⚠️ --profiler 是上游采样过滤器,实测常返回空集——常规取证请去掉(CPU 热点走 dump-list)");
|
|
8381
8406
|
emit(await api.call("ymc/warningCall", body), jsonMode, (data) => {
|
|
8382
8407
|
const d = data;
|
|
8383
8408
|
const rows = Array.isArray(d) ? d : d.rows ?? d.data ?? [];
|
|
@@ -8731,6 +8756,133 @@ async function runYmc(args, globalOpts) {
|
|
|
8731
8756
|
process.exit(1);
|
|
8732
8757
|
}
|
|
8733
8758
|
}
|
|
8759
|
+
const HELP = {
|
|
8760
|
+
status: `bfi ymc status — 查询 YMC 登录会话状态
|
|
8761
|
+
说明:显示 dev/prod 两个 host 组的登录态与过期时间。
|
|
8762
|
+
注意:显示"未登录"不影响取数——首次取数会自动登录(多等几秒),不要停下。`,
|
|
8763
|
+
trace: `bfi ymc trace <trace_id> -e <env> [--ts <毫秒>] [--json]
|
|
8764
|
+
三源合一查询:SLS 业务日志 + warningChain 链路 + ingress 访问日志(诊断首选入口)。
|
|
8765
|
+
参数:
|
|
8766
|
+
<trace_id> 追踪 ID(全局唯一,跨服务,无需 appCode)
|
|
8767
|
+
-e <env> 环境:test/daily/pre/core1-4/commldev
|
|
8768
|
+
--ts <毫秒> Epoch 毫秒时间锚点;默认自动推导(SLS 首条日志时间),
|
|
8769
|
+
SLS 无日志时须显式提供
|
|
8770
|
+
--json 输出完整信封 {code,msg,data}
|
|
8771
|
+
摘要含:span 数/异常数/最大耗时/慢调用与慢SQL告警数/Top慢span/ingress 入口。
|
|
8772
|
+
注意:trace 摘要的入口 URL 可能混入同链路其他入口记录——与目标不符时核对 ingress 明细。`,
|
|
8773
|
+
chain: `bfi ymc chain <trace_id> -e <env> [--ts <毫秒>] [--json]
|
|
8774
|
+
原子源:warningChain 全量 Span 链路(耗时分解/调用树)。trace 三源合一的链路通道单独调用。`,
|
|
8775
|
+
"sls-logs": `bfi ymc sls-logs <trace_id> -e <env> [--ts <毫秒>] [--json]
|
|
8776
|
+
原子源:SLS 业务日志(异常全文/堆栈)。按 traceid 索引检索。`,
|
|
8777
|
+
"sls-raw": `bfi ymc sls-raw "<查询>" -e <env> [-t <time> | --start-time <s> --end-time <e> | --days N] [--line N] [--json]
|
|
8778
|
+
SLS 原始查询(阿里云 SLS 完整语法透传:索引检索 + | SELECT 分析语句)。
|
|
8779
|
+
参数:
|
|
8780
|
+
"<查询>" 查询语句。核心规则:索引检索前置(traceid: xx / "关键词" AND applicationname: xx),
|
|
8781
|
+
禁止 * | SELECT * WHERE 字段=... (WHERE 全扫描必超时)
|
|
8782
|
+
-t <time> 时间简写 10m/2h/3d/4w(默认无时间=服务端超大窗兜底,会命中数天前记录,务必显式指定)
|
|
8783
|
+
--start-time/--end-time 精确窗口 yyyy-MM-dd HH:mm:ss 北京时间(优先于 -t)
|
|
8784
|
+
--days N 按天数回溯(旧参数,等价 -t Nd)
|
|
8785
|
+
--line N 返回行数上限
|
|
8786
|
+
示例:
|
|
8787
|
+
bfi ymc sls-raw 'traceid: abc | SELECT * LIMIT 200' -e daily -t 1d
|
|
8788
|
+
bfi ymc sls-raw '"Exception" AND applicationname: yonbip-scm-pu | SELECT count(*) AS cnt' -e pre -t 3d
|
|
8789
|
+
bfi ymc sls-raw 'applicationname: yonbip-scm-scmmp AND "unaudit" | SELECT traceid, time LIMIT 10' -e core3 -t 1d
|
|
8790
|
+
注意:业务关键词检索必须 applicationname: 限定目标服务(共享路径 URL 全平台都有);
|
|
8791
|
+
traceid/spanid 检索例外(全局唯一)。非索引字段(logger/requesturl)不能进检索语法,只能在 SELECT 里引用。`,
|
|
8792
|
+
"sls-grep": `bfi ymc sls-grep "<关键词>" -e <env> -t <time> [--json]
|
|
8793
|
+
SLS 全文检索聚合(每组计数)。注意:计数上限 100 可能封顶,影响面/精确计数用 sls-raw + GROUP BY。`,
|
|
8794
|
+
slowsql: `bfi ymc slowsql -t <time> -e <env> [--sql-str <表名或片段>] [--md5 <指纹>] [--trace-id <id>] [--app <appCode>] [--no-profiler] [--page N] [--page-size N] [--json]
|
|
8795
|
+
慢 SQL 告警明细(耗时降序;摘要含 服务/耗时/行数/SQL 前段/指纹/调用栈首帧)。
|
|
8796
|
+
参数:
|
|
8797
|
+
-t <time> 时间窗(必填语义,服务端强校验)
|
|
8798
|
+
--sql-str 按 SQL 片段过滤(表名/语句片段)
|
|
8799
|
+
--md5 按 SQL MD5 指纹精确过滤(同类 SQL 归类)
|
|
8800
|
+
--trace-id 按链路过滤。⚠️ 按 trace 查询时不带 --app(traceId 已唯一限定,
|
|
8801
|
+
--app 会截断其他服务的告警行——慢 SQL 归属哪个服务事先未知)
|
|
8802
|
+
--app 服务维度过滤(无 traceId 时必带,裸 appCode)
|
|
8803
|
+
--no-profiler 显式关闭 enableProfiler(默认自动带 'true'——不带该字段上游 500,
|
|
8804
|
+
带了才返回 sqlStack 调用栈)
|
|
8805
|
+
示例:
|
|
8806
|
+
bfi ymc slowsql -t 1d --app yonbip-scm-scmmp -e core3 # 服务维度(SQL 画像)
|
|
8807
|
+
bfi ymc slowsql -t 1d --trace-id abc -e core3 # 链路维度(勿带 --app)`,
|
|
8808
|
+
slowcall: `bfi ymc slowcall -t <time> -e <env> [--trace-id <id>] [--app <appCode>] [--method <方法>] [--min-cost <ms>] [--page N] [--page-size N] [--json]
|
|
8809
|
+
慢调用告警明细(耗时降序;摘要含 服务/耗时/sql/rpc/redis 分解/方法/pod)。
|
|
8810
|
+
参数:
|
|
8811
|
+
--trace-id 按链路过滤。⚠️ 不带 --app(同 slowsql,--app 会截断下游服务告警行)
|
|
8812
|
+
--app 服务维度过滤(裸 appCode)
|
|
8813
|
+
--method 按调用方法过滤
|
|
8814
|
+
--min-cost <ms> 最小耗时过滤(body.costTime=[ms, 999999])
|
|
8815
|
+
(无 --profiler) 历史参数已移除映射——上游 enableProfiler 是"仅返回有 CPU 采样
|
|
8816
|
+
记录"的过滤器,实测任何组合均空集。CPU 热点走 dump-list。
|
|
8817
|
+
示例:
|
|
8818
|
+
bfi ymc slowcall -t 1d --trace-id abc -e core3 # 链路分层分解(跨服务根因链必用)
|
|
8819
|
+
bfi ymc slowcall -t 4w --app yonbip-scm-pu -e pre # 服务慢调用趋势`,
|
|
8820
|
+
exceptions: `bfi ymc exceptions -t <time> -e <env> [--app <appCode>] [--json]
|
|
8821
|
+
异常聚合(exceptionHistory)。--app 传裸微服务名(appId 需 <env>-<appCode> 格式,传裸名上游才查得到)。`,
|
|
8822
|
+
alerts: `bfi ymc alerts -t <time> -e <env> [--level error|warn|info] [--page-size N] [--json]
|
|
8823
|
+
告警明细。--page-size 默认 10;--level 可省。`,
|
|
8824
|
+
"url-stats": `bfi ymc url-stats </uri> -t <time> -e <env> --app <service_name> [--json]
|
|
8825
|
+
URL 性能统计(ingress 访问日志聚合):QPS/avg/P50/P90/P95/P99/状态码分布/慢请求Top10(含 traceId)。
|
|
8826
|
+
参数:
|
|
8827
|
+
--app <service_name> ⚠️ 必带(诊断纪律):共享路径 URL(/bill/* 等通用单据接口)全平台
|
|
8828
|
+
每个业务域都有——不限定服务=全平台混合假面。传裸 appCode 即可
|
|
8829
|
+
(服务端自适应环境前缀 wildcard,如 online-dc-core3-<app>-out)
|
|
8830
|
+
示例:
|
|
8831
|
+
bfi ymc url-stats /bill/unaudit -t 1d -e core3 --app yonbip-scm-scmmp`,
|
|
8832
|
+
ingress: `bfi ymc ingress --trace-id <id> | --uri </path> [-t <time>] -e <env> [--exact] [--app <service_name>] [--size N] [--json]
|
|
8833
|
+
ingress 访问日志明细(网关视角:request_time vs upstream_response_time/状态码/pod/租户)。
|
|
8834
|
+
参数:
|
|
8835
|
+
--trace-id 按链路查(时间可省,默认 30d)
|
|
8836
|
+
--uri 按 URI 查(默认子串匹配,--exact 精确;time 必填)
|
|
8837
|
+
--app service_name 过滤(uri 模式必带,裸 appCode 自适应前缀)
|
|
8838
|
+
--size N 返回条数(默认 100,最大 5000)`,
|
|
8839
|
+
"dump-list": `bfi ymc dump-list -t <time> -e <env> [--app <appCode>] [--type profiler|heap|...] [--json]
|
|
8840
|
+
诊断文件列表(火焰图/JVM dump;CPU 热点取数的正确入口)。`,
|
|
8841
|
+
cases: `bfi ymc cases <search|show|upload|index> [参数]
|
|
8842
|
+
KEDB 案例库(内部诊断先验第一源)。
|
|
8843
|
+
search [--type <t>] [--finger "<指纹>"] [--service <svc>] [--kw "<关键词>"] [--limit N]
|
|
8844
|
+
show <case_id>
|
|
8845
|
+
upload --file <报告.html> [--type slow-req] [--finger "词1,词2"] [--env] [--service]
|
|
8846
|
+
index 案例库索引重建`,
|
|
8847
|
+
wiki: `bfi ymc wiki <search|show> [参数]
|
|
8848
|
+
知识库统一检索(confluence + jira + 文库 ecfile 三源——诊断先验的外部源,勿只查其一)。
|
|
8849
|
+
search "<关键词>" [--source confluence|jira|ecfile] [--limit N] [--titles]
|
|
8850
|
+
show <id> [--source wiki|uap-wiki|gfwiki|gfjira|ecfile]
|
|
8851
|
+
示例:
|
|
8852
|
+
bfi ymc wiki search "/bill/unaudit 超时" # 三源全查(默认)
|
|
8853
|
+
bfi ymc wiki show BIP-BUG-00157126 --source gfjira`,
|
|
8854
|
+
callstat: `bfi ymc callstat -t <time> -e <env> [--page N] [--page-size N] [--json]
|
|
8855
|
+
慢调用统计版(warningCallstat 聚合视图;体检/趋势用)。--app 经 --data 传(见 call)。`,
|
|
8856
|
+
sqlstat: `bfi ymc sqlstat -t <time> -e <env> [--page N] [--page-size N] [--json]
|
|
8857
|
+
慢 SQL 统计版(warningSqlstat 聚合视图)。`,
|
|
8858
|
+
events: `bfi ymc events -e <env> [--type <类型>] [--start-time <s>] [--end-time <e>] [--app <appCode>] [--pipeline <code>] [--histogram] [--json]
|
|
8859
|
+
集群事件明细/直方图。`,
|
|
8860
|
+
"log-url": `bfi ymc log-url -e <env> [--type ingressLog|appLog|instanceLog] [--app <appId>] [--filter-app <ids>]
|
|
8861
|
+
生成 SLS 日志直通 URL(浏览器直接打开的访问/业务/实例日志页签)。`,
|
|
8862
|
+
"sample-list": `bfi ymc sample-list -t <time> -e <env> [--json]
|
|
8863
|
+
采样数据列表。`,
|
|
8864
|
+
rca: `bfi ymc rca -e <env> [-t <time> | --start-time <s> --end-time <e>] [--app <appId>] [--app-code <appCode>] [--json]
|
|
8865
|
+
YMC 官方智能诊断 RCA 全报告。⚠️ 长耗时(实测约 300s),上游需 podId 等参数,失败多因参数不足;客户端超时已设 300s。`,
|
|
8866
|
+
"bpr-download": `bfi ymc bpr-download <pk> -e <env> [-o <输出文件>]
|
|
8867
|
+
BPR 报告 HTML 下载(文件流写盘)。pk 来源:bfi ymc call bpr/list --data '{"page":1,"pageSize":10}' -e <env>。
|
|
8868
|
+
输出默认 bpr_<pk前16>.html。`,
|
|
8869
|
+
call: `bfi ymc call <route> -e <env> [--data '<json>'] [-t <time> | --start-time <s> --end-time <e>] [--timeout <秒>] [--json]
|
|
8870
|
+
通用透传:覆盖全部注册表端点(warningCall/warningSql/exceptionHistory/bpr/list/alert/detail/tool/list/app/history/environment/uba/query ...)。
|
|
8871
|
+
完整清单与参数声明:curl http://172.20.35.178:8901/openapi.json 或 /docs(Swagger UI)。
|
|
8872
|
+
时间参数(-t/--start-time/--end-time)由服务端按端点 time_fields 展开为 beginTs/endTs 等。
|
|
8873
|
+
示例:
|
|
8874
|
+
bfi ymc call warningCallstat --data '{"curAppCode":"yonbip-scm-scmmp","page":1,"pageSize":10}' -e core3 -t 1h
|
|
8875
|
+
bfi ymc call app/history --data '{"appId":"daily-x","queryType":"podCpuUsage"}' -e daily -t 1d`
|
|
8876
|
+
};
|
|
8877
|
+
function printCommandHelp(cmd) {
|
|
8878
|
+
const h = HELP[cmd];
|
|
8879
|
+
if (h) console.log(h);
|
|
8880
|
+
else {
|
|
8881
|
+
console.error(`未知子命令:${cmd}`);
|
|
8882
|
+
printHelp();
|
|
8883
|
+
process.exit(1);
|
|
8884
|
+
}
|
|
8885
|
+
}
|
|
8734
8886
|
function printHelp() {
|
|
8735
8887
|
console.log(`
|
|
8736
8888
|
bfi ymc — 观测查询(v2 API:YMC/Kibana/SLS/trace)
|
|
@@ -8742,8 +8894,9 @@ bfi ymc — 观测查询(v2 API:YMC/Kibana/SLS/trace)
|
|
|
8742
8894
|
sls-logs <trace_id> -e <env> 原子源:SLS 业务日志
|
|
8743
8895
|
sls-raw "<查询>" -e <env> SLS 原始查询(完整查询语法透传)
|
|
8744
8896
|
sls-grep "<关键词>" -e <env> SLS 全文检索聚合(异常历史分布取证)
|
|
8745
|
-
slowsql -t <time> [-e] [--sql-str] [--md5] [--trace-id] [--app] [--profiler]
|
|
8746
|
-
slowcall -t <time> [-e] [--trace-id] [--app] [--method] [--min-cost ms]
|
|
8897
|
+
slowsql -t <time> [-e] [--sql-str] [--md5] [--trace-id] [--app] [--no-profiler]
|
|
8898
|
+
slowcall -t <time> [-e] [--trace-id] [--app] [--method] [--min-cost ms]
|
|
8899
|
+
[--profiler] # ⚠️ 采样过滤器实测常为空集,常规取证勿带
|
|
8747
8900
|
exceptions -t <time> [-e] [--app]
|
|
8748
8901
|
alerts -t <time> [-e] [--level error|warn|info]
|
|
8749
8902
|
url-stats </uri> -t <time> -e <env> [--app <service_name>]
|
|
@@ -8759,8 +8912,11 @@ bfi ymc — 观测查询(v2 API:YMC/Kibana/SLS/trace)
|
|
|
8759
8912
|
-t, --time 时间简写(10m/2h/3d/4w = 过去 N 单位到现在)
|
|
8760
8913
|
--start-time <t> 开始时间 yyyy-MM-dd HH:mm:ss(与 -t 二选一;只传它=到当前)
|
|
8761
8914
|
--end-time <t> 结束时间(须与 --start-time 同传)
|
|
8762
|
-
--json 输出原始 JSON
|
|
8915
|
+
--json 输出原始 JSON(完整信封 {code,msg,data})
|
|
8916
|
+
--dry-run 只打印将发送的 method/URL/body,不实际请求(无需登录)
|
|
8763
8917
|
--token 覆盖已登录 token(默认用 bfi auth login 的)
|
|
8918
|
+
|
|
8919
|
+
详细帮助:bfi ymc help <命令>(或 bfi ymc <命令> -h)——含参数说明/默认值/示例。
|
|
8764
8920
|
`);
|
|
8765
8921
|
}
|
|
8766
8922
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|